Skip to content

Commit dab6f68

Browse files
committed
lib,src: remove post-gc event infrastructure
Remove the 'gc' event from the v8 module and remove the supporting infrastructure from src/. It gets the axe because: 1. There are currently no users. It was originally conceived as an upstreamed subset of StrongLoop's strong-agent GC metrics, but the strong-agent code base has evolved considerably since that time and has no use anymore for what is in core. 2. The implementation is not quite sound. It calls into JS land from inside the GC epilog and that is unsafe. We could fix that by delaying the callback until a safe time but because there are no users anyway, removing it is all around easier. PR-URL: #174 Reviewed-By: Trevor Norris <[email protected]>
1 parent ebf9f29 commit dab6f68

File tree

5 files changed

+3
-303
lines changed

5 files changed

+3
-303
lines changed

lib/v8.js

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,6 @@
1414

1515
'use strict';
1616

17-
var EventEmitter = require('events');
1817
var v8binding = process.binding('v8');
19-
20-
var v8 = module.exports = new EventEmitter();
21-
v8.getHeapStatistics = v8binding.getHeapStatistics;
22-
v8.setFlagsFromString = v8binding.setFlagsFromString;
23-
24-
25-
function emitGC(before, after) {
26-
v8.emit('gc', before, after);
27-
}
28-
29-
30-
v8.on('newListener', function(name) {
31-
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
32-
v8binding.startGarbageCollectionTracking(emitGC);
33-
}
34-
});
35-
36-
37-
v8.on('removeListener', function(name) {
38-
if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) {
39-
v8binding.stopGarbageCollectionTracking();
40-
}
41-
});
18+
exports.getHeapStatistics = v8binding.getHeapStatistics;
19+
exports.setFlagsFromString = v8binding.setFlagsFromString;

src/env-inl.h

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,6 @@
3434

3535
namespace node {
3636

37-
inline Environment::GCInfo::GCInfo()
38-
: type_(static_cast<v8::GCType>(0)),
39-
flags_(static_cast<v8::GCCallbackFlags>(0)),
40-
timestamp_(0) {
41-
}
42-
43-
inline Environment::GCInfo::GCInfo(v8::Isolate* isolate,
44-
v8::GCType type,
45-
v8::GCCallbackFlags flags,
46-
uint64_t timestamp)
47-
: type_(type),
48-
flags_(flags),
49-
timestamp_(timestamp) {
50-
isolate->GetHeapStatistics(&stats_);
51-
}
52-
53-
inline v8::GCType Environment::GCInfo::type() const {
54-
return type_;
55-
}
56-
57-
inline v8::GCCallbackFlags Environment::GCInfo::flags() const {
58-
return flags_;
59-
}
60-
61-
inline v8::HeapStatistics* Environment::GCInfo::stats() const {
62-
// TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
63-
// lands and makes it way into a stable release.
64-
return const_cast<v8::HeapStatistics*>(&stats_);
65-
}
66-
67-
inline uint64_t Environment::GCInfo::timestamp() const {
68-
return timestamp_;
69-
}
70-
7137
inline Environment::IsolateData* Environment::IsolateData::Get(
7238
v8::Isolate* isolate) {
7339
return static_cast<IsolateData*>(isolate->GetData(kIsolateSlot));
@@ -99,9 +65,7 @@ inline Environment::IsolateData::IsolateData(v8::Isolate* isolate,
9965
PropertyName ## _(isolate, FIXED_ONE_BYTE_STRING(isolate, StringValue)),
10066
PER_ISOLATE_STRING_PROPERTIES(V)
10167
#undef V
102-
ref_count_(0) {
103-
QUEUE_INIT(&gc_tracker_queue_);
104-
}
68+
ref_count_(0) {}
10569

10670
inline uv_loop_t* Environment::IsolateData::event_loop() const {
10771
return event_loop_;
@@ -231,7 +195,6 @@ inline Environment::Environment(v8::Local<v8::Context> context,
231195
set_binding_cache_object(v8::Object::New(isolate()));
232196
set_module_load_list_array(v8::Array::New(isolate()));
233197
RB_INIT(&cares_task_list_);
234-
QUEUE_INIT(&gc_tracker_queue_);
235198
QUEUE_INIT(&req_wrap_queue_);
236199
QUEUE_INIT(&handle_wrap_queue_);
237200
QUEUE_INIT(&handle_cleanup_queue_);

src/env.h

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ namespace node {
258258
V(context, v8::Context) \
259259
V(domain_array, v8::Array) \
260260
V(fs_stats_constructor_function, v8::Function) \
261-
V(gc_info_callback_function, v8::Function) \
262261
V(module_load_list_array, v8::Array) \
263262
V(pipe_constructor_template, v8::FunctionTemplate) \
264263
V(process_object, v8::Object) \
@@ -390,10 +389,6 @@ class Environment {
390389
inline void CleanupHandles();
391390
inline void Dispose();
392391

393-
// Defined in src/node_profiler.cc.
394-
void StartGarbageCollectionTracking(v8::Local<v8::Function> callback);
395-
void StopGarbageCollectionTracking();
396-
397392
void AssignToContext(v8::Local<v8::Context> context);
398393

399394
inline v8::Isolate* isolate() const;
@@ -494,13 +489,10 @@ class Environment {
494489
private:
495490
static const int kIsolateSlot = NODE_ISOLATE_SLOT;
496491

497-
class GCInfo;
498492
class IsolateData;
499493
inline Environment(v8::Local<v8::Context> context, uv_loop_t* loop);
500494
inline ~Environment();
501495
inline IsolateData* isolate_data() const;
502-
void AfterGarbageCollectionCallback(const GCInfo* before,
503-
const GCInfo* after);
504496

505497
enum ContextEmbedderDataIndex {
506498
kContextEmbedderDataIndex = NODE_CONTEXT_EMBEDDER_DATA_INDEX
@@ -520,7 +512,6 @@ class Environment {
520512
ares_task_list cares_task_list_;
521513
bool using_smalloc_alloc_cb_;
522514
bool using_domains_;
523-
QUEUE gc_tracker_queue_;
524515
bool printed_error_;
525516
debugger::Agent debugger_agent_;
526517

@@ -536,26 +527,6 @@ class Environment {
536527
ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
537528
#undef V
538529

539-
class GCInfo {
540-
public:
541-
inline GCInfo();
542-
inline GCInfo(v8::Isolate* isolate,
543-
v8::GCType type,
544-
v8::GCCallbackFlags flags,
545-
uint64_t timestamp);
546-
inline v8::GCType type() const;
547-
inline v8::GCCallbackFlags flags() const;
548-
// TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
549-
// lands and makes it way into a stable release.
550-
inline v8::HeapStatistics* stats() const;
551-
inline uint64_t timestamp() const;
552-
private:
553-
v8::GCType type_;
554-
v8::GCCallbackFlags flags_;
555-
v8::HeapStatistics stats_;
556-
uint64_t timestamp_;
557-
};
558-
559530
// Per-thread, reference-counted singleton.
560531
class IsolateData {
561532
public:
@@ -564,10 +535,6 @@ class Environment {
564535
inline void Put();
565536
inline uv_loop_t* event_loop() const;
566537

567-
// Defined in src/node_profiler.cc.
568-
void StartGarbageCollectionTracking(Environment* env);
569-
void StopGarbageCollectionTracking(Environment* env);
570-
571538
#define V(PropertyName, StringValue) \
572539
inline v8::Local<v8::String> PropertyName() const;
573540
PER_ISOLATE_STRING_PROPERTIES(V)
@@ -578,16 +545,6 @@ class Environment {
578545
inline explicit IsolateData(v8::Isolate* isolate, uv_loop_t* loop);
579546
inline v8::Isolate* isolate() const;
580547

581-
// Defined in src/node_profiler.cc.
582-
static void BeforeGarbageCollection(v8::Isolate* isolate,
583-
v8::GCType type,
584-
v8::GCCallbackFlags flags);
585-
static void AfterGarbageCollection(v8::Isolate* isolate,
586-
v8::GCType type,
587-
v8::GCCallbackFlags flags);
588-
void BeforeGarbageCollection(v8::GCType type, v8::GCCallbackFlags flags);
589-
void AfterGarbageCollection(v8::GCType type, v8::GCCallbackFlags flags);
590-
591548
uv_loop_t* const event_loop_;
592549
v8::Isolate* const isolate_;
593550

@@ -597,9 +554,6 @@ class Environment {
597554
#undef V
598555

599556
unsigned int ref_count_;
600-
QUEUE gc_tracker_queue_;
601-
GCInfo gc_info_before_;
602-
GCInfo gc_info_after_;
603557

604558
DISALLOW_COPY_AND_ASSIGN(IsolateData);
605559
};

src/node_v8.cc

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -31,153 +31,15 @@ namespace node {
3131
using v8::Context;
3232
using v8::Function;
3333
using v8::FunctionCallbackInfo;
34-
using v8::GCCallbackFlags;
35-
using v8::GCType;
3634
using v8::Handle;
37-
using v8::HandleScope;
3835
using v8::HeapStatistics;
3936
using v8::Isolate;
4037
using v8::Local;
41-
using v8::Null;
42-
using v8::Number;
4338
using v8::Object;
4439
using v8::String;
4540
using v8::Uint32;
4641
using v8::V8;
4742
using v8::Value;
48-
using v8::kGCTypeAll;
49-
using v8::kGCTypeMarkSweepCompact;
50-
using v8::kGCTypeScavenge;
51-
52-
53-
void Environment::IsolateData::BeforeGarbageCollection(Isolate* isolate,
54-
GCType type,
55-
GCCallbackFlags flags) {
56-
Get(isolate)->BeforeGarbageCollection(type, flags);
57-
}
58-
59-
60-
void Environment::IsolateData::AfterGarbageCollection(Isolate* isolate,
61-
GCType type,
62-
GCCallbackFlags flags) {
63-
Get(isolate)->AfterGarbageCollection(type, flags);
64-
}
65-
66-
67-
void Environment::IsolateData::BeforeGarbageCollection(GCType type,
68-
GCCallbackFlags flags) {
69-
gc_info_before_ = GCInfo(isolate(), type, flags, uv_hrtime());
70-
}
71-
72-
73-
void Environment::IsolateData::AfterGarbageCollection(GCType type,
74-
GCCallbackFlags flags) {
75-
gc_info_after_ = GCInfo(isolate(), type, flags, uv_hrtime());
76-
77-
// The copy upfront and the remove-then-insert is to avoid corrupting the
78-
// list when the callback removes itself from it. QUEUE_FOREACH() is unsafe
79-
// when the list is mutated while being walked.
80-
ASSERT(QUEUE_EMPTY(&gc_tracker_queue_) == false);
81-
QUEUE queue;
82-
QUEUE* q = QUEUE_HEAD(&gc_tracker_queue_);
83-
QUEUE_SPLIT(&gc_tracker_queue_, q, &queue);
84-
while (QUEUE_EMPTY(&queue) == false) {
85-
q = QUEUE_HEAD(&queue);
86-
QUEUE_REMOVE(q);
87-
QUEUE_INSERT_TAIL(&gc_tracker_queue_, q);
88-
Environment* env = ContainerOf(&Environment::gc_tracker_queue_, q);
89-
env->AfterGarbageCollectionCallback(&gc_info_before_, &gc_info_after_);
90-
}
91-
}
92-
93-
94-
void Environment::IsolateData::StartGarbageCollectionTracking(
95-
Environment* env) {
96-
if (QUEUE_EMPTY(&gc_tracker_queue_)) {
97-
isolate()->AddGCPrologueCallback(BeforeGarbageCollection, v8::kGCTypeAll);
98-
isolate()->AddGCEpilogueCallback(AfterGarbageCollection, v8::kGCTypeAll);
99-
}
100-
ASSERT(QUEUE_EMPTY(&env->gc_tracker_queue_) == true);
101-
QUEUE_INSERT_TAIL(&gc_tracker_queue_, &env->gc_tracker_queue_);
102-
}
103-
104-
105-
void Environment::IsolateData::StopGarbageCollectionTracking(Environment* env) {
106-
ASSERT(QUEUE_EMPTY(&env->gc_tracker_queue_) == false);
107-
QUEUE_REMOVE(&env->gc_tracker_queue_);
108-
QUEUE_INIT(&env->gc_tracker_queue_);
109-
if (QUEUE_EMPTY(&gc_tracker_queue_)) {
110-
isolate()->RemoveGCPrologueCallback(BeforeGarbageCollection);
111-
isolate()->RemoveGCEpilogueCallback(AfterGarbageCollection);
112-
}
113-
}
114-
115-
116-
// Considering a memory constrained environment, creating more objects is less
117-
// than ideal
118-
void Environment::AfterGarbageCollectionCallback(const GCInfo* before,
119-
const GCInfo* after) {
120-
HandleScope handle_scope(isolate());
121-
Context::Scope context_scope(context());
122-
Local<Value> argv[] = { Object::New(isolate()), Object::New(isolate()) };
123-
const GCInfo* infov[] = { before, after };
124-
for (unsigned i = 0; i < ARRAY_SIZE(argv); i += 1) {
125-
Local<Object> obj = argv[i].As<Object>();
126-
const GCInfo* info = infov[i];
127-
switch (info->type()) {
128-
case kGCTypeScavenge:
129-
obj->Set(type_string(), scavenge_string());
130-
break;
131-
case kGCTypeMarkSweepCompact:
132-
obj->Set(type_string(), mark_sweep_compact_string());
133-
break;
134-
default:
135-
UNREACHABLE();
136-
}
137-
obj->Set(flags_string(), Uint32::NewFromUnsigned(isolate(), info->flags()));
138-
obj->Set(timestamp_string(), Number::New(isolate(), info->timestamp()));
139-
// TODO(trevnorris): Setting many object properties in C++ is a significant
140-
// performance hit. Redo this to pass the results to JS and create/set the
141-
// properties there.
142-
#define V(name) \
143-
do { \
144-
obj->Set(name ## _string(), \
145-
Uint32::NewFromUnsigned(isolate(), info->stats()->name())); \
146-
} while (0)
147-
V(total_heap_size);
148-
V(total_heap_size_executable);
149-
V(total_physical_size);
150-
V(used_heap_size);
151-
V(heap_size_limit);
152-
#undef V
153-
}
154-
MakeCallback(this,
155-
Null(isolate()),
156-
gc_info_callback_function(),
157-
ARRAY_SIZE(argv),
158-
argv);
159-
}
160-
161-
162-
void Environment::StartGarbageCollectionTracking(Local<Function> callback) {
163-
ASSERT(gc_info_callback_function().IsEmpty() == true);
164-
set_gc_info_callback_function(callback);
165-
isolate_data()->StartGarbageCollectionTracking(this);
166-
}
167-
168-
169-
void Environment::StopGarbageCollectionTracking() {
170-
ASSERT(gc_info_callback_function().IsEmpty() == false);
171-
isolate_data()->StopGarbageCollectionTracking(this);
172-
set_gc_info_callback_function(Local<Function>());
173-
}
174-
175-
176-
void StartGarbageCollectionTracking(const FunctionCallbackInfo<Value>& args) {
177-
CHECK(args[0]->IsFunction() == true);
178-
Environment* env = Environment::GetCurrent(args);
179-
env->StartGarbageCollectionTracking(args[0].As<Function>());
180-
}
18143

18244

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

20365

204-
void StopGarbageCollectionTracking(const FunctionCallbackInfo<Value>& args) {
205-
Environment::GetCurrent(args)->StopGarbageCollectionTracking();
206-
}
207-
208-
20966
void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) {
21067
String::Utf8Value flags(args[0]);
21168
V8::SetFlagsFromString(*flags, flags.length());
@@ -216,12 +73,6 @@ void InitializeV8Bindings(Handle<Object> target,
21673
Handle<Value> unused,
21774
Handle<Context> context) {
21875
Environment* env = Environment::GetCurrent(context);
219-
env->SetMethod(target,
220-
"startGarbageCollectionTracking",
221-
StartGarbageCollectionTracking);
222-
env->SetMethod(target,
223-
"stopGarbageCollectionTracking",
224-
StopGarbageCollectionTracking);
22576
env->SetMethod(target, "getHeapStatistics", GetHeapStatistics);
22677
env->SetMethod(target, "setFlagsFromString", SetFlagsFromString);
22778
}

0 commit comments

Comments
 (0)