summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTrevor Norris <trev.norris@gmail.com>2015-06-03 15:31:33 -0600
committerTrevor Norris <trev.norris@gmail.com>2015-06-17 12:58:39 -0600
commite56758a5e0ff6822e3105c0e69eb49accc42393c (patch)
tree25cc1ce181450f78f4dbce2a8d4489752c35cf7b /src
parent5d0cee46bb90084e6dcd584deb5bc893862ce3b3 (diff)
downloadandroid-node-v8-e56758a5e0ff6822e3105c0e69eb49accc42393c.tar.gz
android-node-v8-e56758a5e0ff6822e3105c0e69eb49accc42393c.tar.bz2
android-node-v8-e56758a5e0ff6822e3105c0e69eb49accc42393c.zip
async-wrap: add provider id and object info cb
Re-add the wrapper class id to AsyncWrap instances so they can be tracked directly in a heapdump. Previously the class id was given without setting the heap dump wrapper class info provider. Causing a segfault when a heapdump was taken. This has been added, and the label_ set to the given provider name so each instance can be identified. The id will not be set of the passed object has no internal field count. As the class pointer cannot be retrieved from the object. In order to properly report the allocated size of each class, the new pure virtual method self_size() has been introduces. PR-URL: https://github.com/nodejs/io.js/pull/1896 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'src')
-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);