summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/async-wrap-inl.h5
-rw-r--r--src/async-wrap.cc90
-rw-r--r--src/async-wrap.h6
-rw-r--r--src/cares_wrap.cc28
-rw-r--r--src/fs_event_wrap.cc2
-rw-r--r--src/js_stream.h2
-rw-r--r--src/node.cc1
-rw-r--r--src/node_crypto.cc4
-rw-r--r--src/node_crypto.h4
-rw-r--r--src/node_file.cc2
-rw-r--r--src/node_stat_watcher.h2
-rw-r--r--src/node_zlib.cc2
-rw-r--r--src/pipe_wrap.cc2
-rw-r--r--src/pipe_wrap.h2
-rw-r--r--src/process_wrap.cc2
-rw-r--r--src/signal_wrap.cc2
-rw-r--r--src/stream_base-inl.h2
-rw-r--r--src/stream_base.h10
-rw-r--r--src/tcp_wrap.cc1
-rw-r--r--src/tcp_wrap.h2
-rw-r--r--src/timer_wrap.cc2
-rw-r--r--src/tls_wrap.h2
-rw-r--r--src/tty_wrap.h2
-rw-r--r--src/udp_wrap.cc1
-rw-r--r--src/udp_wrap.h2
25 files changed, 175 insertions, 5 deletions
diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h
index bad634ddaf..5841c58faf 100644
--- a/src/async-wrap-inl.h
+++ b/src/async-wrap-inl.h
@@ -18,6 +18,11 @@ inline AsyncWrap::AsyncWrap(Environment* env,
ProviderType provider,
AsyncWrap* parent)
: BaseObject(env, object), bits_(static_cast<uint32_t>(provider) << 1) {
+ // Only set wrapper class id if object will be Wrap'd.
+ if (object->InternalFieldCount() > 0)
+ // Shift provider value over to prevent id collision.
+ persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider);
+
// Check user controlled flag to see if the init callback should run.
if (!env->using_asyncwrap())
return;
diff --git a/src/async-wrap.cc b/src/async-wrap.cc
index 2da6b10293..454681e0c6 100644
--- a/src/async-wrap.cc
+++ b/src/async-wrap.cc
@@ -6,6 +6,7 @@
#include "util-inl.h"
#include "v8.h"
+#include "v8-profiler.h"
using v8::Array;
using v8::Context;
@@ -13,16 +14,95 @@ using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Handle;
using v8::HandleScope;
+using v8::HeapProfiler;
using v8::Integer;
using v8::Isolate;
using v8::Local;
using v8::Object;
+using v8::RetainedObjectInfo;
using v8::TryCatch;
using v8::Value;
using v8::kExternalUint32Array;
namespace node {
+static const char* const provider_names[] = {
+#define V(PROVIDER) \
+ #PROVIDER,
+ NODE_ASYNC_PROVIDER_TYPES(V)
+#undef V
+};
+
+
+class RetainedAsyncInfo: public RetainedObjectInfo {
+ public:
+ explicit RetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap);
+
+ virtual void Dispose() override;
+ virtual bool IsEquivalent(RetainedObjectInfo* other) override;
+ virtual intptr_t GetHash() override;
+ virtual const char* GetLabel() override;
+ virtual intptr_t GetSizeInBytes() override;
+
+ private:
+ const char* label_;
+ const AsyncWrap* wrap_;
+ const int length_;
+};
+
+
+RetainedAsyncInfo::RetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap)
+ : label_(provider_names[class_id - NODE_ASYNC_ID_OFFSET]),
+ wrap_(wrap),
+ length_(wrap->self_size()) {
+}
+
+
+void RetainedAsyncInfo::Dispose() {
+ delete this;
+}
+
+
+bool RetainedAsyncInfo::IsEquivalent(RetainedObjectInfo* other) {
+ return label_ == other->GetLabel() &&
+ wrap_ == static_cast<RetainedAsyncInfo*>(other)->wrap_;
+}
+
+
+intptr_t RetainedAsyncInfo::GetHash() {
+ return reinterpret_cast<intptr_t>(wrap_);
+}
+
+
+const char* RetainedAsyncInfo::GetLabel() {
+ return label_;
+}
+
+
+intptr_t RetainedAsyncInfo::GetSizeInBytes() {
+ return length_;
+}
+
+
+RetainedObjectInfo* WrapperInfo(uint16_t class_id, Handle<Value> wrapper) {
+ // No class_id should be the provider type of NONE.
+ CHECK_NE(NODE_ASYNC_ID_OFFSET, class_id);
+ CHECK(wrapper->IsObject());
+ CHECK(!wrapper.IsEmpty());
+
+ Local<Object> object = wrapper.As<Object>();
+ CHECK_GT(object->InternalFieldCount(), 0);
+
+ AsyncWrap* wrap = Unwrap<AsyncWrap>(object);
+ CHECK_NE(nullptr, wrap);
+
+ return new RetainedAsyncInfo(class_id, wrap);
+}
+
+
+// end RetainedAsyncInfo
+
+
static void EnableHooksJS(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
env->async_hooks()->set_enable_callbacks(1);
@@ -71,6 +151,16 @@ static void Initialize(Handle<Object> target,
}
+void LoadAsyncWrapperInfo(Environment* env) {
+ HeapProfiler* heap_profiler = env->isolate()->GetHeapProfiler();
+#define V(PROVIDER) \
+ heap_profiler->SetWrapperClassInfoProvider( \
+ (NODE_ASYNC_ID_OFFSET + AsyncWrap::PROVIDER_ ## PROVIDER), WrapperInfo);
+ NODE_ASYNC_PROVIDER_TYPES(V)
+#undef V
+}
+
+
Handle<Value> AsyncWrap::MakeCallback(const Handle<Function> cb,
int argc,
Handle<Value>* argv) {
diff --git a/src/async-wrap.h b/src/async-wrap.h
index 5e898fe4c2..bb93872ff7 100644
--- a/src/async-wrap.h
+++ b/src/async-wrap.h
@@ -8,6 +8,8 @@
namespace node {
+#define NODE_ASYNC_ID_OFFSET 0xA1C
+
#define NODE_ASYNC_PROVIDER_TYPES(V) \
V(NONE) \
V(CARES) \
@@ -64,6 +66,8 @@ class AsyncWrap : public BaseObject {
int argc,
v8::Handle<v8::Value>* argv);
+ virtual size_t self_size() const = 0;
+
private:
inline AsyncWrap();
inline bool has_async_queue() const;
@@ -74,6 +78,8 @@ class AsyncWrap : public BaseObject {
uint32_t bits_;
};
+void LoadAsyncWrapperInfo(Environment* env);
+
} // namespace node
diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index c73f8c05cb..d4be7c9b9b 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -51,6 +51,8 @@ using v8::Value;
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
public:
GetAddrInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
+
+ size_t self_size() const override { return sizeof(*this); }
};
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
@@ -66,8 +68,10 @@ static void NewGetAddrInfoReqWrap(const FunctionCallbackInfo<Value>& args) {
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
- public:
- GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
+ public:
+ GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
+
+ size_t self_size() const override { return sizeof(*this); }
};
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
@@ -385,6 +389,8 @@ class QueryAWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -422,6 +428,8 @@ class QueryAaaaWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -459,6 +467,8 @@ class QueryCnameWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -498,6 +508,8 @@ class QueryMxWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -547,6 +559,8 @@ class QueryNsWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -583,6 +597,8 @@ class QueryTxtWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -638,6 +654,8 @@ class QuerySrvWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -692,6 +710,8 @@ class QueryNaptrWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -754,6 +774,8 @@ class QuerySoaWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(unsigned char* buf, int len) override {
HandleScope handle_scope(env()->isolate());
@@ -820,6 +842,8 @@ class GetHostByAddrWrap: public QueryWrap {
return 0;
}
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
void Parse(struct hostent* host) override {
HandleScope handle_scope(env()->isolate());
diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc
index a6ceff2776..e17f9ce58e 100644
--- a/src/fs_event_wrap.cc
+++ b/src/fs_event_wrap.cc
@@ -31,6 +31,8 @@ class FSEventWrap: public HandleWrap {
static void Start(const FunctionCallbackInfo<Value>& args);
static void Close(const FunctionCallbackInfo<Value>& args);
+ size_t self_size() const override { return sizeof(*this); }
+
private:
FSEventWrap(Environment* env, Handle<Object> object);
virtual ~FSEventWrap() override;
diff --git a/src/js_stream.h b/src/js_stream.h
index 6bc763b36e..9f7ba7de27 100644
--- a/src/js_stream.h
+++ b/src/js_stream.h
@@ -28,6 +28,8 @@ class JSStream : public StreamBase, public AsyncWrap {
size_t count,
uv_stream_t* send_handle) override;
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
JSStream(Environment* env, v8::Handle<v8::Object> obj, AsyncWrap* parent);
diff --git a/src/node.cc b/src/node.cc
index f47dd72205..18d0850433 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -3872,6 +3872,7 @@ Environment* CreateEnvironment(Isolate* isolate,
env->set_process_object(process_object);
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
+ LoadAsyncWrapperInfo(env);
return env;
}
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index 48a75d30f7..296ca0a606 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -4546,6 +4546,8 @@ class PBKDF2Request : public AsyncWrap {
error_ = err;
}
+ size_t self_size() const override { return sizeof(*this); }
+
uv_work_t work_req_;
private:
@@ -4776,6 +4778,8 @@ class RandomBytesRequest : public AsyncWrap {
error_ = err;
}
+ size_t self_size() const override { return sizeof(*this); }
+
uv_work_t work_req_;
private:
diff --git a/src/node_crypto.h b/src/node_crypto.h
index 0ef9c02273..3a00b51932 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -308,6 +308,8 @@ class Connection : public SSLWrap<Connection>, public AsyncWrap {
v8::Persistent<v8::String> servername_;
#endif
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EncIn(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -702,6 +704,8 @@ class Certificate : public AsyncWrap {
const char* ExportPublicKey(const char* data, int len);
const char* ExportChallenge(const char* data, int len);
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void VerifySpkac(const v8::FunctionCallbackInfo<v8::Value>& args);
diff --git a/src/node_file.cc b/src/node_file.cc
index c8696f1295..0297b08e68 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -73,6 +73,8 @@ class FSReqWrap: public ReqWrap<uv_fs_t> {
const char* syscall() const { return syscall_; }
const char* data() const { return data_; }
+ size_t self_size() const override { return sizeof(*this); }
+
private:
FSReqWrap(Environment* env,
Local<Object> req,
diff --git a/src/node_stat_watcher.h b/src/node_stat_watcher.h
index bd21479104..e0ef76601f 100644
--- a/src/node_stat_watcher.h
+++ b/src/node_stat_watcher.h
@@ -22,6 +22,8 @@ class StatWatcher : public AsyncWrap {
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
+ size_t self_size() const override { return sizeof(*this); }
+
private:
static void Callback(uv_fs_poll_t* handle,
int status,
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index 58dfce3975..699d5c453c 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -535,6 +535,8 @@ class ZCtx : public AsyncWrap {
}
}
+ size_t self_size() const override { return sizeof(*this); }
+
private:
void Ref() {
if (++refs_ == 1) {
diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc
index 08fed68741..2e1ab5b262 100644
--- a/src/pipe_wrap.cc
+++ b/src/pipe_wrap.cc
@@ -37,6 +37,8 @@ using v8::Value;
class PipeConnectWrap : public ReqWrap<uv_connect_t> {
public:
PipeConnectWrap(Environment* env, Local<Object> req_wrap_obj);
+
+ size_t self_size() const override { return sizeof(*this); }
};
diff --git a/src/pipe_wrap.h b/src/pipe_wrap.h
index 6dc9a01bcd..6c74de984b 100644
--- a/src/pipe_wrap.h
+++ b/src/pipe_wrap.h
@@ -16,6 +16,8 @@ class PipeWrap : public StreamWrap {
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
+ size_t self_size() const override { return sizeof(*this); }
+
private:
PipeWrap(Environment* env,
v8::Handle<v8::Object> object,
diff --git a/src/process_wrap.cc b/src/process_wrap.cc
index 56d1f28e4a..14bbb9c9e9 100644
--- a/src/process_wrap.cc
+++ b/src/process_wrap.cc
@@ -46,6 +46,8 @@ class ProcessWrap : public HandleWrap {
constructor->GetFunction());
}
+ size_t self_size() const override { return sizeof(*this); }
+
private:
static void New(const FunctionCallbackInfo<Value>& args) {
// This constructor should not be exposed to public javascript.
diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc
index 7cceb64560..4811aca53a 100644
--- a/src/signal_wrap.cc
+++ b/src/signal_wrap.cc
@@ -40,6 +40,8 @@ class SignalWrap : public HandleWrap {
constructor->GetFunction());
}
+ size_t self_size() const override { return sizeof(*this); }
+
private:
static void New(const FunctionCallbackInfo<Value>& args) {
// This constructor should not be exposed to public javascript.
diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h
index 26ba54b376..d74b47de60 100644
--- a/src/stream_base-inl.h
+++ b/src/stream_base-inl.h
@@ -92,7 +92,7 @@ WriteWrap* WriteWrap::New(Environment* env,
size_t storage_size = ROUND_UP(sizeof(WriteWrap), kAlignSize) + extra;
char* storage = new char[storage_size];
- return new(storage) WriteWrap(env, obj, wrap, cb);
+ return new(storage) WriteWrap(env, obj, wrap, cb, storage_size);
}
diff --git a/src/stream_base.h b/src/stream_base.h
index dfb0d31c66..31854b3435 100644
--- a/src/stream_base.h
+++ b/src/stream_base.h
@@ -48,6 +48,7 @@ class ShutdownWrap : public ReqWrap<uv_shutdown_t>,
}
inline StreamBase* wrap() const { return wrap_; }
+ size_t self_size() const override { return sizeof(*this); }
private:
StreamBase* const wrap_;
@@ -66,6 +67,8 @@ class WriteWrap: public ReqWrap<uv_write_t>,
inline StreamBase* wrap() const { return wrap_; }
+ size_t self_size() const override { return storage_size_; }
+
static void NewWriteWrap(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(args.IsConstructCall());
}
@@ -76,10 +79,12 @@ class WriteWrap: public ReqWrap<uv_write_t>,
WriteWrap(Environment* env,
v8::Local<v8::Object> obj,
StreamBase* wrap,
- DoneCb cb)
+ DoneCb cb,
+ size_t storage_size)
: ReqWrap(env, obj, AsyncWrap::PROVIDER_WRITEWRAP),
StreamReq<WriteWrap>(cb),
- wrap_(wrap) {
+ wrap_(wrap),
+ storage_size_(storage_size) {
Wrap(obj, this);
}
@@ -96,6 +101,7 @@ class WriteWrap: public ReqWrap<uv_write_t>,
void operator delete(void* ptr) { UNREACHABLE(); }
StreamBase* const wrap_;
+ const size_t storage_size_;
};
class StreamResource {
diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc
index e16e140583..6980f8b28c 100644
--- a/src/tcp_wrap.cc
+++ b/src/tcp_wrap.cc
@@ -37,6 +37,7 @@ using v8::Value;
class TCPConnectWrap : public ReqWrap<uv_connect_t> {
public:
TCPConnectWrap(Environment* env, Local<Object> req_wrap_obj);
+ size_t self_size() const override { return sizeof(*this); }
};
diff --git a/src/tcp_wrap.h b/src/tcp_wrap.h
index c41a36fbeb..ee1e9817b2 100644
--- a/src/tcp_wrap.h
+++ b/src/tcp_wrap.h
@@ -16,6 +16,8 @@ class TCPWrap : public StreamWrap {
uv_tcp_t* UVHandle();
+ size_t self_size() const override { return sizeof(*this); }
+
private:
TCPWrap(Environment* env, v8::Handle<v8::Object> object, AsyncWrap* parent);
~TCPWrap();
diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc
index f65290a516..d2c9a8c9ae 100644
--- a/src/timer_wrap.cc
+++ b/src/timer_wrap.cc
@@ -51,6 +51,8 @@ class TimerWrap : public HandleWrap {
constructor->GetFunction());
}
+ size_t self_size() const override { return sizeof(*this); }
+
private:
static void New(const FunctionCallbackInfo<Value>& args) {
// This constructor should not be exposed to public javascript.
diff --git a/src/tls_wrap.h b/src/tls_wrap.h
index a304475190..b906d78de1 100644
--- a/src/tls_wrap.h
+++ b/src/tls_wrap.h
@@ -50,6 +50,8 @@ class TLSWrap : public crypto::SSLWrap<TLSWrap>,
void NewSessionDoneCb();
+ size_t self_size() const override { return sizeof(*this); }
+
protected:
static const int kClearOutChunkSize = 1024;
diff --git a/src/tty_wrap.h b/src/tty_wrap.h
index 09cd71e781..6d423e1ae5 100644
--- a/src/tty_wrap.h
+++ b/src/tty_wrap.h
@@ -15,6 +15,8 @@ class TTYWrap : public StreamWrap {
uv_tty_t* UVHandle();
+ size_t self_size() const override { return sizeof(*this); }
+
private:
TTYWrap(Environment* env,
v8::Handle<v8::Object> object,
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc
index 3183d1f9f5..fe0ed76dd5 100644
--- a/src/udp_wrap.cc
+++ b/src/udp_wrap.cc
@@ -36,6 +36,7 @@ class SendWrap : public ReqWrap<uv_udp_send_t> {
public:
SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback);
inline bool have_callback() const;
+ size_t self_size() const override { return sizeof(*this); }
private:
const bool have_callback_;
};
diff --git a/src/udp_wrap.h b/src/udp_wrap.h
index 0a33ae8cb2..3373cb9a2d 100644
--- a/src/udp_wrap.h
+++ b/src/udp_wrap.h
@@ -37,6 +37,8 @@ class UDPWrap: public HandleWrap {
static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
uv_udp_t* UVHandle();
+ size_t self_size() const override { return sizeof(*this); }
+
private:
UDPWrap(Environment* env, v8::Handle<v8::Object> object, AsyncWrap* parent);