From bf95c3ebeebcb83cee331432db9895a61c204069 Mon Sep 17 00:00:00 2001 From: Brandon Papworth Date: Thu, 11 Sep 2014 18:54:29 -0500 Subject: [PATCH] / applied changes originally performed by deepak1556 in this pull request: [https://github.com/lloyd/node-memwatch/pull/56] --- src/heapdiff.cc | 125 ++++++++++++++++++++++++------------------------ src/heapdiff.hh | 7 +-- src/init.cc | 2 +- src/memwatch.cc | 106 ++++++++++++++++++++-------------------- src/memwatch.hh | 5 +- 5 files changed, 122 insertions(+), 123 deletions(-) diff --git a/src/heapdiff.cc b/src/heapdiff.cc index 4055751..823e9c6 100644 --- a/src/heapdiff.cc +++ b/src/heapdiff.cc @@ -1,12 +1,6 @@ /* * 2012|lloyd|http://wtfpl.org */ - -#include "heapdiff.hh" -#include "util.hh" - -#include - #include #include #include @@ -15,6 +9,9 @@ #include // abs() #include // time() +#include "heapdiff.hh" +#include "util.hh" + using namespace v8; using namespace node; using namespace std; @@ -22,7 +19,7 @@ using namespace std; static bool s_inProgress = false; static time_t s_startTime; -bool heapdiff::HeapDiff::InProgress() +bool heapdiff::HeapDiff::InProgress() { return s_inProgress; } @@ -48,29 +45,27 @@ heapdiff::HeapDiff::~HeapDiff() void heapdiff::HeapDiff::Initialize ( v8::Handle target ) { - v8::HandleScope scope; - v8::Local t = v8::FunctionTemplate::New(New); + NanScope(); + + v8::Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(String::NewSymbol("HeapDiff")); + t->SetClassName(NanNew("HeapDiff")); NODE_SET_PROTOTYPE_METHOD(t, "end", End); - target->Set(v8::String::NewSymbol( "HeapDiff"), t->GetFunction()); + target->Set(NanNew( "HeapDiff"), t->GetFunction()); } -v8::Handle -heapdiff::HeapDiff::New (const v8::Arguments& args) +NAN_METHOD(heapdiff::HeapDiff::New) { // Don't blow up when the caller says "new require('memwatch').HeapDiff()" // issue #30 // stolen from: https://github.com/kkaefer/node-cpp-modules/commit/bd9432026affafd8450ecfd9b49b7dc647b6d348 if (!args.IsConstructCall()) { - return ThrowException( - Exception::TypeError( - String::New("Use the new operator to create instances of this object."))); + return NanThrowTypeError("Use the new operator to create instances of this object."); } - v8::HandleScope scope; + NanScope(); // allocate the underlying c++ class and wrap it up in the this pointer HeapDiff * self = new HeapDiff(); @@ -79,22 +74,28 @@ heapdiff::HeapDiff::New (const v8::Arguments& args) // take a snapshot and save a pointer to it s_inProgress = true; s_startTime = time(NULL); - self->before = v8::HeapProfiler::TakeSnapshot(v8::String::New("")); + +#if (NODE_MODULE_VERSION > 0x000B) + self->before = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(NanNew(""), NULL); +#else + self->before = v8::HeapProfiler::TakeSnapshot(NanNew(""), HeapSnapshot::kFull, NULL); +#endif + s_inProgress = false; - return args.This(); + NanReturnValue(args.This()); } static string handleToStr(const Handle & str) { - String::Utf8Value utfString(str->ToString()); - return *utfString; + String::Utf8Value utfString(str->ToString()); + return *utfString; } static void buildIDSet(set * seen, const HeapGraphNode* cur, int & s) { - v8::HandleScope scope; + NanScope(); // cycle detection if (seen->find(cur->GetId()) != seen->end()) { @@ -210,66 +211,66 @@ static void manageChange(changeset & changes, const HeapGraphNode * node, bool a static Handle changesetToObject(changeset & changes) { - v8::HandleScope scope; - Local a = Array::New(); + NanEscapableScope(); + Local a = NanNew(); for (changeset::iterator i = changes.begin(); i != changes.end(); i++) { - Local d = Object::New(); - d->Set(String::New("what"), String::New(i->first.c_str())); - d->Set(String::New("size_bytes"), Integer::New(i->second.size)); - d->Set(String::New("size"), String::New(mw_util::niceSize(i->second.size).c_str())); - d->Set(String::New("+"), Integer::New(i->second.added)); - d->Set(String::New("-"), Integer::New(i->second.released)); + Local d = NanNew(); + d->Set(NanNew("what"), NanNew(i->first.c_str())); + d->Set(NanNew("size_bytes"), NanNew(i->second.size)); + d->Set(NanNew("size"), NanNew(mw_util::niceSize(i->second.size).c_str())); + d->Set(NanNew("+"), NanNew(i->second.added)); + d->Set(NanNew("-"), NanNew(i->second.released)); a->Set(a->Length(), d); } - return scope.Close(a); + return NanEscapeScope(a); } static v8::Handle compare(const v8::HeapSnapshot * before, const v8::HeapSnapshot * after) { - v8::HandleScope scope; + NanEscapableScope(); int s, diffBytes; - Local o = Object::New(); + Local o = NanNew(); // first let's append summary information - Local b = Object::New(); - b->Set(String::New("nodes"), Integer::New(before->GetNodesCount())); - b->Set(String::New("time"), NODE_UNIXTIME_V8(s_startTime)); - o->Set(String::New("before"), b); + Local b = NanNew(); + b->Set(NanNew("nodes"), NanNew(before->GetNodesCount())); + //b->Set(NanNew("time"), s_startTime); + o->Set(NanNew("before"), b); - Local a = Object::New(); - a->Set(String::New("nodes"), Integer::New(after->GetNodesCount())); - a->Set(String::New("time"), NODE_UNIXTIME_V8(time(NULL))); - o->Set(String::New("after"), a); + Local a = NanNew(); + a->Set(NanNew("nodes"), NanNew(after->GetNodesCount())); + //a->Set(NanNew("time"), time(NULL)); + o->Set(NanNew("after"), a); // now let's get allocations by name set beforeIDs, afterIDs; s = 0; buildIDSet(&beforeIDs, before->GetRoot(), s); - b->Set(String::New("size_bytes"), Integer::New(s)); - b->Set(String::New("size"), String::New(mw_util::niceSize(s).c_str())); + b->Set(NanNew("size_bytes"), NanNew(s)); + b->Set(NanNew("size"), NanNew(mw_util::niceSize(s).c_str())); diffBytes = s; s = 0; buildIDSet(&afterIDs, after->GetRoot(), s); - a->Set(String::New("size_bytes"), Integer::New(s)); - a->Set(String::New("size"), String::New(mw_util::niceSize(s).c_str())); + a->Set(NanNew("size_bytes"), NanNew(s)); + a->Set(NanNew("size"), NanNew(mw_util::niceSize(s).c_str())); diffBytes = s - diffBytes; - Local c = Object::New(); - c->Set(String::New("size_bytes"), Integer::New(diffBytes)); - c->Set(String::New("size"), String::New(mw_util::niceSize(diffBytes).c_str())); - o->Set(String::New("change"), c); + Local c = NanNew(); + c->Set(NanNew("size_bytes"), NanNew(diffBytes)); + c->Set(NanNew("size"), NanNew(mw_util::niceSize(diffBytes).c_str())); + o->Set(NanNew("change"), c); // before - after will reveal nodes released (memory freed) vector changedIDs; setDiff(beforeIDs, afterIDs, changedIDs); - c->Set(String::New("freed_nodes"), Integer::New(changedIDs.size())); + c->Set(NanNew("freed_nodes"), NanNew(changedIDs.size())); // here's where we'll collect all the summary information changeset changes; @@ -285,23 +286,22 @@ compare(const v8::HeapSnapshot * before, const v8::HeapSnapshot * after) // after - before will reveal nodes added (memory allocated) setDiff(afterIDs, beforeIDs, changedIDs); - c->Set(String::New("allocated_nodes"), Integer::New(changedIDs.size())); + c->Set(NanNew("allocated_nodes"), NanNew(changedIDs.size())); for (unsigned long i = 0; i < changedIDs.size(); i++) { const HeapGraphNode * n = after->GetNodeById(changedIDs[i]); manageChange(changes, n, true); } - c->Set(String::New("details"), changesetToObject(changes)); + c->Set(NanNew("details"), changesetToObject(changes)); - return scope.Close(o); + return NanEscapeScope(o); } -v8::Handle -heapdiff::HeapDiff::End( const Arguments& args ) +NAN_METHOD(heapdiff::HeapDiff::End) { // take another snapshot and compare them - v8::HandleScope scope; + NanScope(); HeapDiff *t = Unwrap( args.This() ); @@ -309,15 +309,16 @@ heapdiff::HeapDiff::End( const Arguments& args ) // approach seems to be an exception, cause nothing else makes // sense. if (t->ended) { - return v8::ThrowException( - v8::Exception::Error( - v8::String::New("attempt to end() a HeapDiff that was " - "already ended"))); + return NanThrowError("attempt to end() a HeapDiff that was already ended"); } t->ended = true; s_inProgress = true; - t->after = v8::HeapProfiler::TakeSnapshot(v8::String::New("")); +#if (NODE_MODULE_VERSION > 0x000B) + t->after = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(NanNew(""), NULL); +#else + t->after = v8::HeapProfiler::TakeSnapshot(NanNew(""), HeapSnapshot::kFull, NULL); +#endif s_inProgress = false; v8::Handle comparison = compare(t->before, t->after); @@ -328,5 +329,5 @@ heapdiff::HeapDiff::End( const Arguments& args ) ((HeapSnapshot *) t->after)->Delete(); t->after = NULL; - return scope.Close(comparison); + NanReturnValue(comparison); } diff --git a/src/heapdiff.hh b/src/heapdiff.hh index 557bbe4..592858c 100644 --- a/src/heapdiff.hh +++ b/src/heapdiff.hh @@ -8,16 +8,17 @@ #include #include #include +#include -namespace heapdiff +namespace heapdiff { class HeapDiff : public node::ObjectWrap { public: static void Initialize ( v8::Handle target ); - static v8::Handle New( const v8::Arguments& args ); - static v8::Handle End( const v8::Arguments& args ); + static NAN_METHOD(New); + static NAN_METHOD(End); static bool InProgress(); protected: diff --git a/src/init.cc b/src/init.cc index 7d289f8..00df1a2 100644 --- a/src/init.cc +++ b/src/init.cc @@ -11,7 +11,7 @@ extern "C" { void init (v8::Handle target) { - v8::HandleScope scope; + NanScope(); heapdiff::HeapDiff::Initialize(target); NODE_SET_METHOD(target, "upon_gc", memwatch::upon_gc); diff --git a/src/memwatch.cc b/src/memwatch.cc index d64d544..a216514 100644 --- a/src/memwatch.cc +++ b/src/memwatch.cc @@ -21,7 +21,7 @@ using namespace v8; using namespace node; Handle g_context; -Handle g_cb; +NanCallback *g_cb; struct Baton { uv_work_t req; @@ -67,29 +67,29 @@ static struct static Handle getLeakReport(size_t heapUsage) { - HandleScope scope; + NanEscapableScope(); size_t growth = heapUsage - s_stats.leak_base_start; int now = time(NULL); int delta = now - s_stats.leak_time_start; - Local leakReport = Object::New(); - leakReport->Set(String::New("start"), NODE_UNIXTIME_V8(s_stats.leak_time_start)); - leakReport->Set(String::New("end"), NODE_UNIXTIME_V8(now)); - leakReport->Set(String::New("growth"), Integer::New(growth)); + Local leakReport = NanNew(); + //leakReport->Set(NanNew("start"), NODE_UNIXTIME_V8(s_stats.leak_time_start)); + //leakReport->Set(NanNew("end"), NODE_UNIXTIME_V8(now)); + leakReport->Set(NanNew("growth"), NanNew(growth)); std::stringstream ss; ss << "heap growth over 5 consecutive GCs (" << mw_util::niceDelta(delta) << ") - " << mw_util::niceSize(growth / ((double) delta / (60.0 * 60.0))) << "/hr"; - leakReport->Set(String::New("reason"), String::New(ss.str().c_str())); + leakReport->Set(NanNew("reason"), NanNew(ss.str().c_str())); - return scope.Close(leakReport); + return NanEscapeScope(leakReport); } static void AsyncMemwatchAfter(uv_work_t* request) { - HandleScope scope; + NanScope(); Baton * b = (Baton *) request->data; @@ -121,11 +121,11 @@ static void AsyncMemwatchAfter(uv_work_t* request) { // emit a leak report! Handle argv[3]; - argv[0] = Boolean::New(false); + argv[0] = NanNew(false); // the type of event to emit - argv[1] = String::New("leak"); + argv[1] = NanNew("leak"); argv[2] = getLeakReport(b->heapUsage); - g_cb->Call(g_context, 3, argv); + g_cb->Call(3, argv); } } else { s_stats.consecutive_growth = 0; @@ -171,37 +171,36 @@ static void AsyncMemwatchAfter(uv_work_t* request) { } // if there are any listeners, it's time to emit! - if (!g_cb.IsEmpty()) { + if (!g_cb->IsEmpty()) { Handle argv[3]; // magic argument to indicate to the callback all we want to know is whether there are // listeners (here we don't) - argv[0] = Boolean::New(true); - - Handle haveListeners = g_cb->Call(g_context, 1, argv); - - if (haveListeners->BooleanValue()) { - double ut= 0.0; - if (s_stats.base_ancient) { - ut = (double) ROUND(((double) (s_stats.base_recent - s_stats.base_ancient) / - (double) s_stats.base_ancient) * 1000.0) / 10.0; - } - - // ok, there are listeners, we actually must serialize and emit this stats event - Local stats = Object::New(); - stats->Set(String::New("num_full_gc"), Integer::New(s_stats.gc_full)); - stats->Set(String::New("num_inc_gc"), Integer::New(s_stats.gc_inc)); - stats->Set(String::New("heap_compactions"), Integer::New(s_stats.gc_compact)); - stats->Set(String::New("usage_trend"), Number::New(ut)); - stats->Set(String::New("estimated_base"), Integer::New(s_stats.base_recent)); - stats->Set(String::New("current_base"), Integer::New(s_stats.last_base)); - stats->Set(String::New("min"), Integer::New(s_stats.base_min)); - stats->Set(String::New("max"), Integer::New(s_stats.base_max)); - argv[0] = Boolean::New(false); - // the type of event to emit - argv[1] = String::New("stats"); - argv[2] = stats; - g_cb->Call(g_context, 3, argv); + argv[0] = NanNew(true); + + //Handle haveListeners = g_cb->call(1, argv); + + + double ut= 0.0; + if (s_stats.base_ancient) { + ut = (double) ROUND(((double) (s_stats.base_recent - s_stats.base_ancient) / + (double) s_stats.base_ancient) * 1000.0) / 10.0; } + + // ok, there are listeners, we actually must serialize and emit this stats event + Local stats = NanNew(); + stats->Set(NanNew("num_full_gc"), NanNew(s_stats.gc_full)); + stats->Set(NanNew("num_inc_gc"), NanNew(s_stats.gc_inc)); + stats->Set(NanNew("heap_compactions"), NanNew(s_stats.gc_compact)); + stats->Set(NanNew("usage_trend"), NanNew(ut)); + stats->Set(NanNew("estimated_base"), NanNew(s_stats.base_recent)); + stats->Set(NanNew("current_base"), NanNew(s_stats.last_base)); + stats->Set(NanNew("min"), NanNew(s_stats.base_min)); + stats->Set(NanNew("max"), NanNew(s_stats.base_max)); + argv[0] = NanNew(false); + // the type of event to emit + argv[1] = NanNew("stats"); + argv[2] = stats; + g_cb->Call(3, argv); } } @@ -214,12 +213,12 @@ void memwatch::after_gc(GCType type, GCCallbackFlags flags) { if (heapdiff::HeapDiff::InProgress()) return; - HandleScope scope; + NanScope(); Baton * baton = new Baton; v8::HeapStatistics hs; - v8::V8::GetHeapStatistics(&hs); + NanGetHeapStatistics(&hs); baton->heapUsage = hs.used_heap_size(); baton->type = type; @@ -227,27 +226,24 @@ void memwatch::after_gc(GCType type, GCCallbackFlags flags) baton->req.data = (void *) baton; // schedule our work to run in a moment, once gc has fully completed. - // - // here we pass a noop work function to work around a flaw in libuv, + // + // here we pass a noop work function to work around a flaw in libuv, // uv_queue_work on unix works fine, but will will crash on - // windows. see: https://github.com/joyent/libuv/pull/629 + // windows. see: https://github.com/joyent/libuv/pull/629 uv_queue_work(uv_default_loop(), &(baton->req), - noop_work_func, (uv_after_work_cb)AsyncMemwatchAfter); - - scope.Close(Undefined()); + noop_work_func, (uv_after_work_cb)AsyncMemwatchAfter); } -Handle memwatch::upon_gc(const Arguments& args) { - HandleScope scope; +NAN_METHOD(memwatch::upon_gc) { + NanScope(); if (args.Length() >= 1 && args[0]->IsFunction()) { - g_cb = Persistent::New(Handle::Cast(args[0])); - g_context = Persistent::New(Context::GetCalling()->Global()); + g_cb = new NanCallback(args[0].As()); } - return scope.Close(Undefined()); + NanReturnValue(NanUndefined()); } -Handle memwatch::trigger_gc(const Arguments& args) { - HandleScope scope; +NAN_METHOD(memwatch::trigger_gc) { + NanScope(); while(!V8::IdleNotification()) {}; - return scope.Close(Undefined()); + NanReturnValue(NanUndefined()); } diff --git a/src/memwatch.hh b/src/memwatch.hh index dc3db96..73cde27 100644 --- a/src/memwatch.hh +++ b/src/memwatch.hh @@ -6,11 +6,12 @@ #define __MEMWATCH_HH #include +#include namespace memwatch { - v8::Handle upon_gc(const v8::Arguments& args); - v8::Handle trigger_gc(const v8::Arguments& args); + NAN_METHOD(upon_gc); + NAN_METHOD(trigger_gc); void after_gc(v8::GCType type, v8::GCCallbackFlags flags); };