Skip to content

Commit e56758a

Browse files
committed
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: #1896 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 5d0cee4 commit e56758a

25 files changed

+175
-5
lines changed

‎src/async-wrap-inl.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ inline AsyncWrap::AsyncWrap(Environment* env,
1818
ProviderType provider,
1919
AsyncWrap* parent)
2020
: BaseObject(env, object), bits_(static_cast<uint32_t>(provider) << 1){
21+
// Only set wrapper class id if object will be Wrap'd.
22+
if (object->InternalFieldCount() > 0)
23+
// Shift provider value over to prevent id collision.
24+
persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider);
25+
2126
// Check user controlled flag to see if the init callback should run.
2227
if (!env->using_asyncwrap())
2328
return;

‎src/async-wrap.cc‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,103 @@
66
#include"util-inl.h"
77

88
#include"v8.h"
9+
#include"v8-profiler.h"
910

1011
using v8::Array;
1112
using v8::Context;
1213
using v8::Function;
1314
using v8::FunctionCallbackInfo;
1415
using v8::Handle;
1516
using v8::HandleScope;
17+
using v8::HeapProfiler;
1618
using v8::Integer;
1719
using v8::Isolate;
1820
using v8::Local;
1921
using v8::Object;
22+
using v8::RetainedObjectInfo;
2023
using v8::TryCatch;
2124
using v8::Value;
2225
using v8::kExternalUint32Array;
2326

2427
namespacenode{
2528

29+
staticconstchar* const provider_names[] ={
30+
#defineV(PROVIDER) \
31+
#PROVIDER,
32+
NODE_ASYNC_PROVIDER_TYPES(V)
33+
#undef V
34+
};
35+
36+
37+
classRetainedAsyncInfo: publicRetainedObjectInfo{
38+
public:
39+
explicitRetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap);
40+
41+
virtualvoidDispose() override;
42+
virtualboolIsEquivalent(RetainedObjectInfo* other) override;
43+
virtualintptr_tGetHash() override;
44+
virtualconstchar* GetLabel() override;
45+
virtualintptr_tGetSizeInBytes() override;
46+
47+
private:
48+
constchar* label_;
49+
const AsyncWrap* wrap_;
50+
constint length_;
51+
};
52+
53+
54+
RetainedAsyncInfo::RetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap)
55+
: label_(provider_names[class_id - NODE_ASYNC_ID_OFFSET]),
56+
wrap_(wrap),
57+
length_(wrap->self_size()){
58+
}
59+
60+
61+
voidRetainedAsyncInfo::Dispose(){
62+
deletethis;
63+
}
64+
65+
66+
boolRetainedAsyncInfo::IsEquivalent(RetainedObjectInfo* other){
67+
return label_ == other->GetLabel() &&
68+
wrap_ == static_cast<RetainedAsyncInfo*>(other)->wrap_;
69+
}
70+
71+
72+
intptr_tRetainedAsyncInfo::GetHash(){
73+
returnreinterpret_cast<intptr_t>(wrap_);
74+
}
75+
76+
77+
constchar* RetainedAsyncInfo::GetLabel(){
78+
return label_;
79+
}
80+
81+
82+
intptr_tRetainedAsyncInfo::GetSizeInBytes(){
83+
return length_;
84+
}
85+
86+
87+
RetainedObjectInfo* WrapperInfo(uint16_t class_id, Handle<Value> wrapper){
88+
// No class_id should be the provider type of NONE.
89+
CHECK_NE(NODE_ASYNC_ID_OFFSET, class_id);
90+
CHECK(wrapper->IsObject());
91+
CHECK(!wrapper.IsEmpty());
92+
93+
Local<Object> object = wrapper.As<Object>();
94+
CHECK_GT(object->InternalFieldCount(), 0);
95+
96+
AsyncWrap* wrap = Unwrap<AsyncWrap>(object);
97+
CHECK_NE(nullptr, wrap);
98+
99+
returnnewRetainedAsyncInfo(class_id, wrap);
100+
}
101+
102+
103+
// end RetainedAsyncInfo
104+
105+
26106
staticvoidEnableHooksJS(const FunctionCallbackInfo<Value>& args){
27107
Environment* env = Environment::GetCurrent(args);
28108
env->async_hooks()->set_enable_callbacks(1);
@@ -71,6 +151,16 @@ static void Initialize(Handle<Object> target,
71151
}
72152

73153

154+
voidLoadAsyncWrapperInfo(Environment* env){
155+
HeapProfiler* heap_profiler = env->isolate()->GetHeapProfiler();
156+
#defineV(PROVIDER) \
157+
heap_profiler->SetWrapperClassInfoProvider( \
158+
(NODE_ASYNC_ID_OFFSET + AsyncWrap::PROVIDER_ ## PROVIDER), WrapperInfo);
159+
NODE_ASYNC_PROVIDER_TYPES(V)
160+
#undef V
161+
}
162+
163+
74164
Handle<Value> AsyncWrap::MakeCallback(const Handle<Function> cb,
75165
int argc,
76166
Handle<Value>* argv){

‎src/async-wrap.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespacenode{
1010

11+
#defineNODE_ASYNC_ID_OFFSET0xA1C
12+
1113
#defineNODE_ASYNC_PROVIDER_TYPES(V) \
1214
V(NONE) \
1315
V(CARES) \
@@ -64,6 +66,8 @@ class AsyncWrap : public BaseObject{
6466
int argc,
6567
v8::Handle<v8::Value>* argv);
6668

69+
virtualsize_tself_size() const = 0;
70+
6771
private:
6872
inlineAsyncWrap();
6973
inlineboolhas_async_queue() const;
@@ -74,6 +78,8 @@ class AsyncWrap : public BaseObject{
7478
uint32_t bits_;
7579
};
7680

81+
voidLoadAsyncWrapperInfo(Environment* env);
82+
7783
} // namespace node
7884

7985

‎src/cares_wrap.cc‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ using v8::Value;
5151
classGetAddrInfoReqWrap : publicReqWrap<uv_getaddrinfo_t>{
5252
public:
5353
GetAddrInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
54+
55+
size_tself_size() constoverride{returnsizeof(*this)}
5456
};
5557

5658
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
@@ -66,8 +68,10 @@ static void NewGetAddrInfoReqWrap(const FunctionCallbackInfo<Value>& args){
6668

6769

6870
classGetNameInfoReqWrap : publicReqWrap<uv_getnameinfo_t>{
69-
public:
70-
GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
71+
public:
72+
GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
73+
74+
size_tself_size() constoverride{returnsizeof(*this)}
7175
};
7276

7377
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
@@ -385,6 +389,8 @@ class QueryAWrap: public QueryWrap{
385389
return0;
386390
}
387391

392+
size_tself_size() constoverride{returnsizeof(*this)}
393+
388394
protected:
389395
voidParse(unsignedchar* buf, int len) override{
390396
HandleScope handle_scope(env()->isolate());
@@ -422,6 +428,8 @@ class QueryAaaaWrap: public QueryWrap{
422428
return0;
423429
}
424430

431+
size_tself_size() constoverride{returnsizeof(*this)}
432+
425433
protected:
426434
voidParse(unsignedchar* buf, int len) override{
427435
HandleScope handle_scope(env()->isolate());
@@ -459,6 +467,8 @@ class QueryCnameWrap: public QueryWrap{
459467
return0;
460468
}
461469

470+
size_tself_size() constoverride{returnsizeof(*this)}
471+
462472
protected:
463473
voidParse(unsignedchar* buf, int len) override{
464474
HandleScope handle_scope(env()->isolate());
@@ -498,6 +508,8 @@ class QueryMxWrap: public QueryWrap{
498508
return0;
499509
}
500510

511+
size_tself_size() constoverride{returnsizeof(*this)}
512+
501513
protected:
502514
voidParse(unsignedchar* buf, int len) override{
503515
HandleScope handle_scope(env()->isolate());
@@ -547,6 +559,8 @@ class QueryNsWrap: public QueryWrap{
547559
return0;
548560
}
549561

562+
size_tself_size() constoverride{returnsizeof(*this)}
563+
550564
protected:
551565
voidParse(unsignedchar* buf, int len) override{
552566
HandleScope handle_scope(env()->isolate());
@@ -583,6 +597,8 @@ class QueryTxtWrap: public QueryWrap{
583597
return0;
584598
}
585599

600+
size_tself_size() constoverride{returnsizeof(*this)}
601+
586602
protected:
587603
voidParse(unsignedchar* buf, int len) override{
588604
HandleScope handle_scope(env()->isolate());
@@ -638,6 +654,8 @@ class QuerySrvWrap: public QueryWrap{
638654
return0;
639655
}
640656

657+
size_tself_size() constoverride{returnsizeof(*this)}
658+
641659
protected:
642660
voidParse(unsignedchar* buf, int len) override{
643661
HandleScope handle_scope(env()->isolate());
@@ -692,6 +710,8 @@ class QueryNaptrWrap: public QueryWrap{
692710
return0;
693711
}
694712

713+
size_tself_size() constoverride{returnsizeof(*this)}
714+
695715
protected:
696716
voidParse(unsignedchar* buf, int len) override{
697717
HandleScope handle_scope(env()->isolate());
@@ -754,6 +774,8 @@ class QuerySoaWrap: public QueryWrap{
754774
return0;
755775
}
756776

777+
size_tself_size() constoverride{returnsizeof(*this)}
778+
757779
protected:
758780
voidParse(unsignedchar* buf, int len) override{
759781
HandleScope handle_scope(env()->isolate());
@@ -820,6 +842,8 @@ class GetHostByAddrWrap: public QueryWrap{
820842
return0;
821843
}
822844

845+
size_tself_size() constoverride{returnsizeof(*this)}
846+
823847
protected:
824848
voidParse(structhostent* host) override{
825849
HandleScope handle_scope(env()->isolate());

‎src/fs_event_wrap.cc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class FSEventWrap: public HandleWrap{
3131
staticvoidStart(const FunctionCallbackInfo<Value>& args);
3232
staticvoidClose(const FunctionCallbackInfo<Value>& args);
3333

34+
size_tself_size() constoverride{returnsizeof(*this)}
35+
3436
private:
3537
FSEventWrap(Environment* env, Handle<Object> object);
3638
virtual~FSEventWrap() override;

‎src/js_stream.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class JSStream : public StreamBase, public AsyncWrap{
2828
size_t count,
2929
uv_stream_t* send_handle) override;
3030

31+
size_tself_size() constoverride{returnsizeof(*this)}
32+
3133
protected:
3234
JSStream(Environment* env, v8::Handle<v8::Object> obj, AsyncWrap* parent);
3335

‎src/node.cc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,6 +3872,7 @@ Environment* CreateEnvironment(Isolate* isolate,
38723872
env->set_process_object(process_object);
38733873

38743874
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
3875+
LoadAsyncWrapperInfo(env);
38753876

38763877
return env;
38773878
}

‎src/node_crypto.cc‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4546,6 +4546,8 @@ class PBKDF2Request : public AsyncWrap{
45464546
error_ = err;
45474547
}
45484548

4549+
size_tself_size() constoverride{returnsizeof(*this)}
4550+
45494551
uv_work_t work_req_;
45504552

45514553
private:
@@ -4776,6 +4778,8 @@ class RandomBytesRequest : public AsyncWrap{
47764778
error_ = err;
47774779
}
47784780

4781+
size_tself_size() constoverride{returnsizeof(*this)}
4782+
47794783
uv_work_t work_req_;
47804784

47814785
private:

‎src/node_crypto.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ class Connection : public SSLWrap<Connection>, public AsyncWrap{
308308
v8::Persistent<v8::String> servername_;
309309
#endif
310310

311+
size_tself_size() constoverride{returnsizeof(*this)}
312+
311313
protected:
312314
staticvoidNew(const v8::FunctionCallbackInfo<v8::Value>& args);
313315
staticvoidEncIn(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -702,6 +704,8 @@ class Certificate : public AsyncWrap{
702704
constchar* ExportPublicKey(constchar* data, int len);
703705
constchar* ExportChallenge(constchar* data, int len);
704706

707+
size_tself_size() constoverride{returnsizeof(*this)}
708+
705709
protected:
706710
staticvoidNew(const v8::FunctionCallbackInfo<v8::Value>& args);
707711
staticvoidVerifySpkac(const v8::FunctionCallbackInfo<v8::Value>& args);

‎src/node_file.cc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class FSReqWrap: public ReqWrap<uv_fs_t>{
7373
constchar* syscall() const{return syscall_}
7474
constchar* data() const{return data_}
7575

76+
size_tself_size() constoverride{returnsizeof(*this)}
77+
7678
private:
7779
FSReqWrap(Environment* env,
7880
Local<Object> req,

0 commit comments

Comments
(0)