Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib,src: remove post-gc event infrastructure #174

Merged
merged 1 commit into from
Dec 18, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions lib/v8.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,6 @@

'use strict';

var EventEmitter = require('events');
var v8binding = process.binding('v8');

var v8 = module.exports = new EventEmitter();
v8.getHeapStatistics = v8binding.getHeapStatistics;
v8.setFlagsFromString = v8binding.setFlagsFromString;


function emitGC(before, after) {
v8.emit('gc', before, after);
}


v8.on('newListener', function(name) {
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
v8binding.startGarbageCollectionTracking(emitGC);
}
});


v8.on('removeListener', function(name) {
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
v8binding.stopGarbageCollectionTracking();
}
});
exports.getHeapStatistics = v8binding.getHeapStatistics;
exports.setFlagsFromString = v8binding.setFlagsFromString;
39 changes: 1 addition & 38 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,40 +34,6 @@

namespace node {

inline Environment::GCInfo::GCInfo()
: type_(static_cast<v8::GCType>(0)),
flags_(static_cast<v8::GCCallbackFlags>(0)),
timestamp_(0) {
}

inline Environment::GCInfo::GCInfo(v8::Isolate* isolate,
v8::GCType type,
v8::GCCallbackFlags flags,
uint64_t timestamp)
: type_(type),
flags_(flags),
timestamp_(timestamp) {
isolate->GetHeapStatistics(&stats_);
}

inline v8::GCType Environment::GCInfo::type() const {
return type_;
}

inline v8::GCCallbackFlags Environment::GCInfo::flags() const {
return flags_;
}

inline v8::HeapStatistics* Environment::GCInfo::stats() const {
// TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
// lands and makes it way into a stable release.
return const_cast<v8::HeapStatistics*>(&stats_);
}

inline uint64_t Environment::GCInfo::timestamp() const {
return timestamp_;
}

inline Environment::IsolateData* Environment::IsolateData::Get(
v8::Isolate* isolate) {
return static_cast<IsolateData*>(isolate->GetData(kIsolateSlot));
Expand Down Expand Up @@ -99,9 +65,7 @@ inline Environment::IsolateData::IsolateData(v8::Isolate* isolate,
PropertyName ## _(isolate, FIXED_ONE_BYTE_STRING(isolate, StringValue)),
PER_ISOLATE_STRING_PROPERTIES(V)
#undef V
ref_count_(0) {
QUEUE_INIT(&gc_tracker_queue_);
}
ref_count_(0) {}

inline uv_loop_t* Environment::IsolateData::event_loop() const {
return event_loop_;
Expand Down Expand Up @@ -231,7 +195,6 @@ inline Environment::Environment(v8::Local<v8::Context> context,
set_binding_cache_object(v8::Object::New(isolate()));
set_module_load_list_array(v8::Array::New(isolate()));
RB_INIT(&cares_task_list_);
QUEUE_INIT(&gc_tracker_queue_);
QUEUE_INIT(&req_wrap_queue_);
QUEUE_INIT(&handle_wrap_queue_);
QUEUE_INIT(&handle_cleanup_queue_);
Expand Down
46 changes: 0 additions & 46 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ namespace node {
V(context, v8::Context) \
V(domain_array, v8::Array) \
V(fs_stats_constructor_function, v8::Function) \
V(gc_info_callback_function, v8::Function) \
V(module_load_list_array, v8::Array) \
V(pipe_constructor_template, v8::FunctionTemplate) \
V(process_object, v8::Object) \
Expand Down Expand Up @@ -390,10 +389,6 @@ class Environment {
inline void CleanupHandles();
inline void Dispose();

// Defined in src/node_profiler.cc.
void StartGarbageCollectionTracking(v8::Local<v8::Function> callback);
void StopGarbageCollectionTracking();

void AssignToContext(v8::Local<v8::Context> context);

inline v8::Isolate* isolate() const;
Expand Down Expand Up @@ -494,13 +489,10 @@ class Environment {
private:
static const int kIsolateSlot = NODE_ISOLATE_SLOT;

class GCInfo;
class IsolateData;
inline Environment(v8::Local<v8::Context> context, uv_loop_t* loop);
inline ~Environment();
inline IsolateData* isolate_data() const;
void AfterGarbageCollectionCallback(const GCInfo* before,
const GCInfo* after);

enum ContextEmbedderDataIndex {
kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX
Expand All @@ -520,7 +512,6 @@ class Environment {
ares_task_list cares_task_list_;
bool using_smalloc_alloc_cb_;
bool using_domains_;
QUEUE gc_tracker_queue_;
bool printed_error_;
debugger::Agent debugger_agent_;

Expand All @@ -536,26 +527,6 @@ class Environment {
ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
#undef V

class GCInfo {
public:
inline GCInfo();
inline GCInfo(v8::Isolate* isolate,
v8::GCType type,
v8::GCCallbackFlags flags,
uint64_t timestamp);
inline v8::GCType type() const;
inline v8::GCCallbackFlags flags() const;
// TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
// lands and makes it way into a stable release.
inline v8::HeapStatistics* stats() const;
inline uint64_t timestamp() const;
private:
v8::GCType type_;
v8::GCCallbackFlags flags_;
v8::HeapStatistics stats_;
uint64_t timestamp_;
};

// Per-thread, reference-counted singleton.
class IsolateData {
public:
Expand All @@ -564,10 +535,6 @@ class Environment {
inline void Put();
inline uv_loop_t* event_loop() const;

// Defined in src/node_profiler.cc.
void StartGarbageCollectionTracking(Environment* env);
void StopGarbageCollectionTracking(Environment* env);

#define V(PropertyName, StringValue) \
inline v8::Local<v8::String> PropertyName() const;
PER_ISOLATE_STRING_PROPERTIES(V)
Expand All @@ -578,16 +545,6 @@ class Environment {
inline explicit IsolateData(v8::Isolate* isolate, uv_loop_t* loop);
inline v8::Isolate* isolate() const;

// Defined in src/node_profiler.cc.
static void BeforeGarbageCollection(v8::Isolate* isolate,
v8::GCType type,
v8::GCCallbackFlags flags);
static void AfterGarbageCollection(v8::Isolate* isolate,
v8::GCType type,
v8::GCCallbackFlags flags);
void BeforeGarbageCollection(v8::GCType type, v8::GCCallbackFlags flags);
void AfterGarbageCollection(v8::GCType type, v8::GCCallbackFlags flags);

uv_loop_t* const event_loop_;
v8::Isolate* const isolate_;

Expand All @@ -597,9 +554,6 @@ class Environment {
#undef V

unsigned int ref_count_;
QUEUE gc_tracker_queue_;
GCInfo gc_info_before_;
GCInfo gc_info_after_;

DISALLOW_COPY_AND_ASSIGN(IsolateData);
};
Expand Down
149 changes: 0 additions & 149 deletions src/node_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,153 +31,15 @@ namespace node {
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::GCCallbackFlags;
using v8::GCType;
using v8::Handle;
using v8::HandleScope;
using v8::HeapStatistics;
using v8::Isolate;
using v8::Local;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Uint32;
using v8::V8;
using v8::Value;
using v8::kGCTypeAll;
using v8::kGCTypeMarkSweepCompact;
using v8::kGCTypeScavenge;


void Environment::IsolateData::BeforeGarbageCollection(Isolate* isolate,
GCType type,
GCCallbackFlags flags) {
Get(isolate)->BeforeGarbageCollection(type, flags);
}


void Environment::IsolateData::AfterGarbageCollection(Isolate* isolate,
GCType type,
GCCallbackFlags flags) {
Get(isolate)->AfterGarbageCollection(type, flags);
}


void Environment::IsolateData::BeforeGarbageCollection(GCType type,
GCCallbackFlags flags) {
gc_info_before_ = GCInfo(isolate(), type, flags, uv_hrtime());
}


void Environment::IsolateData::AfterGarbageCollection(GCType type,
GCCallbackFlags flags) {
gc_info_after_ = GCInfo(isolate(), type, flags, uv_hrtime());

// The copy upfront and the remove-then-insert is to avoid corrupting the
// list when the callback removes itself from it. QUEUE_FOREACH() is unsafe
// when the list is mutated while being walked.
ASSERT(QUEUE_EMPTY(&gc_tracker_queue_) == false);
QUEUE queue;
QUEUE* q = QUEUE_HEAD(&gc_tracker_queue_);
QUEUE_SPLIT(&gc_tracker_queue_, q, &queue);
while (QUEUE_EMPTY(&queue) == false) {
q = QUEUE_HEAD(&queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&gc_tracker_queue_, q);
Environment* env = ContainerOf(&Environment::gc_tracker_queue_, q);
env->AfterGarbageCollectionCallback(&gc_info_before_, &gc_info_after_);
}
}


void Environment::IsolateData::StartGarbageCollectionTracking(
Environment* env) {
if (QUEUE_EMPTY(&gc_tracker_queue_)) {
isolate()->AddGCPrologueCallback(BeforeGarbageCollection, v8::kGCTypeAll);
isolate()->AddGCEpilogueCallback(AfterGarbageCollection, v8::kGCTypeAll);
}
ASSERT(QUEUE_EMPTY(&env->gc_tracker_queue_) == true);
QUEUE_INSERT_TAIL(&gc_tracker_queue_, &env->gc_tracker_queue_);
}


void Environment::IsolateData::StopGarbageCollectionTracking(Environment* env) {
ASSERT(QUEUE_EMPTY(&env->gc_tracker_queue_) == false);
QUEUE_REMOVE(&env->gc_tracker_queue_);
QUEUE_INIT(&env->gc_tracker_queue_);
if (QUEUE_EMPTY(&gc_tracker_queue_)) {
isolate()->RemoveGCPrologueCallback(BeforeGarbageCollection);
isolate()->RemoveGCEpilogueCallback(AfterGarbageCollection);
}
}


// Considering a memory constrained environment, creating more objects is less
// than ideal
void Environment::AfterGarbageCollectionCallback(const GCInfo* before,
const GCInfo* after) {
HandleScope handle_scope(isolate());
Context::Scope context_scope(context());
Local<Value> argv[] = { Object::New(isolate()), Object::New(isolate()) };
const GCInfo* infov[] = { before, after };
for (unsigned i = 0; i < ARRAY_SIZE(argv); i += 1) {
Local<Object> obj = argv[i].As<Object>();
const GCInfo* info = infov[i];
switch (info->type()) {
case kGCTypeScavenge:
obj->Set(type_string(), scavenge_string());
break;
case kGCTypeMarkSweepCompact:
obj->Set(type_string(), mark_sweep_compact_string());
break;
default:
UNREACHABLE();
}
obj->Set(flags_string(), Uint32::NewFromUnsigned(isolate(), info->flags()));
obj->Set(timestamp_string(), Number::New(isolate(), info->timestamp()));
// TODO(trevnorris): Setting many object properties in C++ is a significant
// performance hit. Redo this to pass the results to JS and create/set the
// properties there.
#define V(name) \
do { \
obj->Set(name ## _string(), \
Uint32::NewFromUnsigned(isolate(), info->stats()->name())); \
} while (0)
V(total_heap_size);
V(total_heap_size_executable);
V(total_physical_size);
V(used_heap_size);
V(heap_size_limit);
#undef V
}
MakeCallback(this,
Null(isolate()),
gc_info_callback_function(),
ARRAY_SIZE(argv),
argv);
}


void Environment::StartGarbageCollectionTracking(Local<Function> callback) {
ASSERT(gc_info_callback_function().IsEmpty() == true);
set_gc_info_callback_function(callback);
isolate_data()->StartGarbageCollectionTracking(this);
}


void Environment::StopGarbageCollectionTracking() {
ASSERT(gc_info_callback_function().IsEmpty() == false);
isolate_data()->StopGarbageCollectionTracking(this);
set_gc_info_callback_function(Local<Function>());
}


void StartGarbageCollectionTracking(const FunctionCallbackInfo<Value>& args) {
CHECK(args[0]->IsFunction() == true);
Environment* env = Environment::GetCurrent(args);
env->StartGarbageCollectionTracking(args[0].As<Function>());
}


void GetHeapStatistics(const FunctionCallbackInfo<Value>& args) {
Expand All @@ -201,11 +63,6 @@ void GetHeapStatistics(const FunctionCallbackInfo<Value>& args) {
}


void StopGarbageCollectionTracking(const FunctionCallbackInfo<Value>& args) {
Environment::GetCurrent(args)->StopGarbageCollectionTracking();
}


void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) {
String::Utf8Value flags(args[0]);
V8::SetFlagsFromString(*flags, flags.length());
Expand All @@ -216,12 +73,6 @@ void InitializeV8Bindings(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);
env->SetMethod(target,
"startGarbageCollectionTracking",
StartGarbageCollectionTracking);
env->SetMethod(target,
"stopGarbageCollectionTracking",
StopGarbageCollectionTracking);
env->SetMethod(target, "getHeapStatistics", GetHeapStatistics);
env->SetMethod(target, "setFlagsFromString", SetFlagsFromString);
}
Expand Down
Loading