Skip to content

Commit 3f5d584

Browse files
committed
domain: share object and state with native land
Change process.domain to use a getter/setter and access that property via an array index. These are much faster to get from c++, and it can be passed to _setupDomainUse and stored as a Persistent<Array>. InDomain() and GetDomain() as trivial ways to access the domain information in the native layer. Important because we'll be able to quickly access if a domain is active. Instead of just whether the domain module has been loaded.
1 parent 2ef1782 commit 3f5d584

4 files changed

Lines changed: 61 additions & 13 deletions

File tree

lib/domain.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,25 @@ var endMethods = ['end', 'abort', 'destroy', 'destroySoon'];
3232
// a few side effects.
3333
events.usingDomains = true;
3434

35+
// overwrite process.domain with a getter/setter that will allow for more
36+
// effective optimizations
37+
var _domain = [null];
38+
Object.defineProperty(process, 'domain', {
39+
enumerable: true,
40+
get: function() {
41+
return _domain[0];
42+
},
43+
set: function(arg) {
44+
return _domain[0] = arg;
45+
}
46+
});
47+
48+
// objects with external array data are excellent ways to communicate state
49+
// between js and c++ w/o much overhead
50+
var _domain_flag = {};
51+
3552
// let the process know we're using domains
36-
process._setupDomainUse();
53+
process._setupDomainUse(_domain, _domain_flag);
3754

3855
exports.Domain = Domain;
3956

@@ -64,6 +81,7 @@ Domain.prototype.enter = function() {
6481
// to push it onto the stack so that we can pop it later.
6582
exports.active = process.domain = this;
6683
stack.push(this);
84+
_domain_flag[0] = stack.length;
6785
};
6886

6987
Domain.prototype.exit = function() {
@@ -74,6 +92,7 @@ Domain.prototype.exit = function() {
7492
do {
7593
d = stack.pop();
7694
} while (d && d !== this);
95+
_domain_flag[0] = stack.length;
7796

7897
exports.active = stack[stack.length - 1];
7998
process.domain = exports.active;

src/node.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ Persistent<Object> process_p;
132132
static Persistent<Function> process_tickCallback;
133133
static Persistent<Object> binding_cache;
134134
static Persistent<Array> module_load_list;
135+
static Persistent<Array> p_domain_box;
135136

136137
static Cached<String> exports_symbol;
137138

@@ -183,6 +184,11 @@ static struct {
183184
uint32_t last_threw;
184185
} tick_infobox;
185186

187+
// easily communicate domain depth
188+
static struct {
189+
uint32_t count;
190+
} domain_flag;
191+
186192
#ifdef OPENSSL_NPN_NEGOTIATED
187193
static bool use_npn = true;
188194
#else
@@ -917,6 +923,33 @@ void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
917923
Local<Function> tdc = tdc_v.As<Function>();
918924
process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback"), tdc);
919925
process_tickCallback.Reset(node_isolate, tdc);
926+
if (!args[0]->IsArray()) {
927+
fprintf(stderr, "_setupDomainUse first argument must be an array\n");
928+
abort();
929+
}
930+
p_domain_box.Reset(node_isolate, args[0].As<Array>());
931+
if (!args[1]->IsObject()) {
932+
fprintf(stderr, "_setupDomainUse second argument must be an object\n");
933+
abort();
934+
}
935+
Local<Object> flag = args[1].As<Object>();
936+
flag->SetIndexedPropertiesToExternalArrayData(&domain_flag,
937+
kExternalUnsignedIntArray,
938+
1);
939+
}
940+
941+
942+
bool InDomain() {
943+
return using_domains && domain_flag.count > 0;
944+
}
945+
946+
947+
Handle<Value> GetDomain() {
948+
// no domain can exist if no domain module has been loaded
949+
if (!InDomain() || p_domain_box.IsEmpty())
950+
return Null(node_isolate);
951+
952+
return PersistentToLocal(node_isolate, p_domain_box)->Get(0);
920953
}
921954

922955

src/node_internals.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ NO_RETURN void FatalError(const char* location, const char* message);
218218
abort(); \
219219
}
220220

221-
// allow for quick domain check
222-
extern bool using_domains;
223-
224221
enum Endianness {
225222
kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h.
226223
kBigEndian
@@ -378,6 +375,10 @@ inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
378375
length);
379376
}
380377

378+
bool InDomain();
379+
380+
v8::Handle<v8::Value> GetDomain();
381+
381382
} // namespace node
382383

383384
#endif // SRC_NODE_INTERNALS_H_

src/req_wrap.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define SRC_REQ_WRAP_H_
2424

2525
#include "node.h"
26+
#include "node_internals.h"
2627
#include "queue.h"
2728

2829
namespace node {
@@ -40,16 +41,10 @@ class ReqWrap {
4041
if (object.IsEmpty()) object = v8::Object::New();
4142
persistent().Reset(node_isolate, object);
4243

43-
if (using_domains) {
44-
v8::Local<v8::Value> domain = v8::Context::GetCurrent()
45-
->Global()
46-
->Get(process_symbol)
47-
->ToObject()
48-
->Get(domain_symbol);
49-
50-
if (domain->IsObject()) {
44+
if (InDomain()) {
45+
v8::Local<v8::Value> domain = GetDomain();
46+
if (domain->IsObject())
5147
object->Set(domain_symbol, domain);
52-
}
5348
}
5449

5550
QUEUE_INSERT_TAIL(&req_wrap_queue, &req_wrap_queue_);

0 commit comments

Comments
 (0)