Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

node: use a single, per-tick HandleScope

Avoids the creation and concomitant destruction of lots of tiny HandleScopes.

This change may increase peak memory usage with some workloads. The real
memory usage doesn't change but the garbage collector runs less often.

Speeds up the http_simple benchmark by about 2.5% in release builds and
over 11% in debug builds.
  • Loading branch information...
commit 23cf4b267badf22be96045c324b60c7dadaeedc5 1 parent fccb92b
@bnoordhuis authored
View
7 src/handle_wrap.cc
@@ -51,8 +51,6 @@ void HandleWrap::Initialize(Handle<Object> target) {
Handle<Value> HandleWrap::Ref(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(HandleWrap)
uv_ref(wrap->handle__);
@@ -63,8 +61,6 @@ Handle<Value> HandleWrap::Ref(const Arguments& args) {
Handle<Value> HandleWrap::Unref(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(HandleWrap)
uv_unref(wrap->handle__);
@@ -75,8 +71,6 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
Handle<Value> HandleWrap::Close(const Arguments& args) {
- HandleScope scope;
-
HandleWrap *wrap = static_cast<HandleWrap*>(
args.Holder()->GetPointerFromInternalField(0));
@@ -98,7 +92,6 @@ HandleWrap::HandleWrap(Handle<Object> object, uv_handle_t* h) {
h->data = this;
}
- HandleScope scope;
assert(object_.IsEmpty());
assert(object->InternalFieldCount() > 0);
object_ = v8::Persistent<v8::Object>::New(object);
View
16 src/node.cc
@@ -2898,16 +2898,24 @@ int Start(int argc, char *argv[]) {
Handle<Object> process_l = SetupProcessObject(argc, argv);
v8_typed_array::AttachBindings(context->Global());
- // Create all the objects, load modules, do everything.
- // so your next reading stop should be node::Load()!
- Load(process_l);
+ {
+ HandleScope temp_scope;
+ // Create all the objects, load modules, do everything.
+ // so your next reading stop should be node::Load()!
+ Load(process_l);
+ }
// All our arguments are loaded. We've evaluated all of the scripts. We
// might even have created TCP servers. Now we enter the main eventloop. If
// there are no watchers on the loop (except for the ones that were
// uv_unref'd) then this function exits. As long as there are active
// watchers, it blocks.
- uv_run(uv_default_loop());
+ uv_loop_t* loop = uv_default_loop();
+
+ while (true) {
+ HandleScope temp_scope;
+ if (!uv_run_once(loop)) break;
+ }
EmitExit(process_l);
RunAtExit();
View
22 src/node_http_parser.cc
@@ -296,8 +296,6 @@ class Parser : public ObjectWrap {
HTTP_DATA_CB(on_body) {
- HandleScope scope;
-
Local<Value> cb = handle_->Get(on_body_sym);
if (!cb->IsFunction())
return 0;
@@ -320,8 +318,6 @@ class Parser : public ObjectWrap {
HTTP_CB(on_message_complete) {
- HandleScope scope;
-
if (num_fields_)
Flush(); // Flush trailing HTTP headers.
@@ -342,8 +338,6 @@ class Parser : public ObjectWrap {
static Handle<Value> New(const Arguments& args) {
- HandleScope scope;
-
http_parser_type type =
static_cast<http_parser_type>(args[0]->Int32Value());
@@ -374,8 +368,6 @@ class Parser : public ObjectWrap {
// var bytesParsed = parser->execute(buffer, off, len);
static Handle<Value> Execute(const Arguments& args) {
- HandleScope scope;
-
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!current_buffer);
@@ -438,16 +430,14 @@ class Parser : public ObjectWrap {
Local<Object> obj = e->ToObject();
obj->Set(String::NewSymbol("bytesParsed"), nparsed_obj);
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
- return scope.Close(e);
+ return e;
} else {
- return scope.Close(nparsed_obj);
+ return nparsed_obj;
}
}
static Handle<Value> Finish(const Arguments& args) {
- HandleScope scope;
-
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!current_buffer);
@@ -464,7 +454,7 @@ class Parser : public ObjectWrap {
Local<Object> obj = e->ToObject();
obj->Set(String::NewSymbol("bytesParsed"), Integer::New(0));
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
- return scope.Close(e);
+ return e;
}
return Undefined();
@@ -472,8 +462,6 @@ class Parser : public ObjectWrap {
static Handle<Value> Reinitialize(const Arguments& args) {
- HandleScope scope;
-
http_parser_type type =
static_cast<http_parser_type>(args[0]->Int32Value());
@@ -507,8 +495,6 @@ class Parser : public ObjectWrap {
// spill headers and request path to JS land
void Flush() {
- HandleScope scope;
-
Local<Value> cb = handle_->Get(on_headers_sym);
if (!cb->IsFunction())
@@ -551,8 +537,6 @@ class Parser : public ObjectWrap {
void InitHttpParser(Handle<Object> target) {
- HandleScope scope;
-
Local<FunctionTemplate> t = FunctionTemplate::New(Parser::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(String::NewSymbol("HTTPParser"));
View
39 src/stream_wrap.cc
@@ -41,7 +41,6 @@ using v8::Handle;
using v8::Local;
using v8::Persistent;
using v8::Value;
-using v8::HandleScope;
using v8::FunctionTemplate;
using v8::String;
using v8::Function;
@@ -93,8 +92,6 @@ void StreamWrap::Initialize(Handle<Object> target) {
slab_allocator = new SlabAllocator(SLAB_SIZE);
AtExit(DeleteSlabAllocator, NULL);
- HandleScope scope;
-
HandleWrap::Initialize(target);
buffer_sym = NODE_PSYMBOL("buffer");
@@ -122,14 +119,11 @@ void StreamWrap::SetHandle(uv_handle_t* h) {
void StreamWrap::UpdateWriteQueueSize() {
- HandleScope scope;
object_->Set(write_queue_size_sym, Integer::New(stream_->write_queue_size));
}
Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
@@ -144,13 +138,11 @@ Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
int r = uv_read_stop(wrap->stream_);
@@ -158,7 +150,7 @@ Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
@@ -172,8 +164,6 @@ uv_buf_t StreamWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
void StreamWrap::OnReadCommon(uv_stream_t* handle, ssize_t nread,
uv_buf_t buf, uv_handle_type pending) {
- HandleScope scope;
-
StreamWrap* wrap = static_cast<StreamWrap*>(handle->data);
// We should not be getting this callback if someone as already called
@@ -242,8 +232,6 @@ void StreamWrap::OnRead2(uv_pipe_t* handle, ssize_t nread, uv_buf_t buf,
Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
// The first argument is a buffer.
@@ -256,7 +244,7 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
uv_err_t err;
err.code = UV_ENOBUFS;
SetErrno(err);
- return scope.Close(v8::Null());
+ return v8::Null();
}
char* storage = new char[sizeof(WriteWrap)];
@@ -283,16 +271,15 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap();
delete[] storage;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
template <WriteEncoding encoding>
Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
- HandleScope scope;
int r;
UNWRAP(StreamWrap)
@@ -340,7 +327,7 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
uv_err_t err;
err.code = UV_ENOBUFS;
SetErrno(err);
- return scope.Close(v8::Null());
+ return v8::Null();
}
char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
@@ -416,9 +403,9 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap();
delete[] storage;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -442,8 +429,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
WriteWrap* req_wrap = (WriteWrap*) req->data;
StreamWrap* wrap = (StreamWrap*) req->handle->data;
- HandleScope scope;
-
// The wrap and request objects should still be there.
assert(req_wrap->object_.IsEmpty() == false);
assert(wrap->object_.IsEmpty() == false);
@@ -468,8 +453,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
ShutdownWrap* req_wrap = new ShutdownWrap();
@@ -481,9 +464,9 @@ Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
if (r) {
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -496,8 +479,6 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
assert(req_wrap->object_.IsEmpty() == false);
assert(wrap->object_.IsEmpty() == false);
- HandleScope scope;
-
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
View
55 src/tcp_wrap.cc
@@ -50,7 +50,6 @@ using v8::Context;
using v8::Function;
using v8::FunctionTemplate;
using v8::Handle;
-using v8::HandleScope;
using v8::Integer;
using v8::Local;
using v8::Object;
@@ -75,11 +74,7 @@ Local<Object> TCPWrap::Instantiate() {
// If this assert fire then process.binding('tcp_wrap') hasn't been
// called yet.
assert(tcpConstructor.IsEmpty() == false);
-
- HandleScope scope;
- Local<Object> obj = tcpConstructor->NewInstance();
-
- return scope.Close(obj);
+ return tcpConstructor->NewInstance();
}
@@ -87,8 +82,6 @@ void TCPWrap::Initialize(Handle<Object> target) {
HandleWrap::Initialize(target);
StreamWrap::Initialize(target);
- HandleScope scope;
-
Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->SetClassName(String::NewSymbol("TCP"));
@@ -146,11 +139,10 @@ Handle<Value> TCPWrap::New(const Arguments& args) {
// normal function.
assert(args.IsConstructCall());
- HandleScope scope;
TCPWrap* wrap = new TCPWrap(args.This());
assert(wrap);
- return scope.Close(args.This());
+ return args.This();
}
@@ -169,7 +161,6 @@ TCPWrap::~TCPWrap() {
Handle<Value> TCPWrap::GetSockName(const Arguments& args) {
- HandleScope scope;
struct sockaddr_storage address;
UNWRAP(TCPWrap)
@@ -185,12 +176,11 @@ Handle<Value> TCPWrap::GetSockName(const Arguments& args) {
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
- return scope.Close(AddressToJS(addr));
+ return AddressToJS(addr);
}
Handle<Value> TCPWrap::GetPeerName(const Arguments& args) {
- HandleScope scope;
struct sockaddr_storage address;
UNWRAP(TCPWrap)
@@ -206,13 +196,11 @@ Handle<Value> TCPWrap::GetPeerName(const Arguments& args) {
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
- return scope.Close(AddressToJS(addr));
+ return AddressToJS(addr);
}
Handle<Value> TCPWrap::SetNoDelay(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
int enable = static_cast<int>(args[0]->BooleanValue());
@@ -225,8 +213,6 @@ Handle<Value> TCPWrap::SetNoDelay(const Arguments& args) {
Handle<Value> TCPWrap::SetKeepAlive(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
int enable = args[0]->Int32Value();
@@ -242,8 +228,6 @@ Handle<Value> TCPWrap::SetKeepAlive(const Arguments& args) {
#ifdef _WIN32
Handle<Value> TCPWrap::SetSimultaneousAccepts(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
bool enable = args[0]->BooleanValue();
@@ -258,8 +242,6 @@ Handle<Value> TCPWrap::SetSimultaneousAccepts(const Arguments& args) {
Handle<Value> TCPWrap::Bind(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
String::AsciiValue ip_address(args[0]);
@@ -271,13 +253,11 @@ Handle<Value> TCPWrap::Bind(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
Handle<Value> TCPWrap::Bind6(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
String::AsciiValue ip6_address(args[0]);
@@ -289,13 +269,11 @@ Handle<Value> TCPWrap::Bind6(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
Handle<Value> TCPWrap::Listen(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
int backlog = args[0]->Int32Value();
@@ -305,13 +283,11 @@ Handle<Value> TCPWrap::Listen(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
- HandleScope scope;
-
TCPWrap* wrap = static_cast<TCPWrap*>(handle->data);
assert(&wrap->handle_ == (uv_tcp_t*)handle);
@@ -347,8 +323,6 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
ConnectWrap* req_wrap = (ConnectWrap*) req->data;
TCPWrap* wrap = (TCPWrap*) req->handle->data;
- HandleScope scope;
-
// The wrap and request objects should still be there.
assert(req_wrap->object_.IsEmpty() == false);
assert(wrap->object_.IsEmpty() == false);
@@ -372,8 +346,6 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
Handle<Value> TCPWrap::Connect(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
String::AsciiValue ip_address(args[0]);
@@ -394,16 +366,14 @@ Handle<Value> TCPWrap::Connect(const Arguments& args) {
if (r) {
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
Handle<Value> TCPWrap::Connect6(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(TCPWrap)
String::AsciiValue ip_address(args[0]);
@@ -421,9 +391,9 @@ Handle<Value> TCPWrap::Connect6(const Arguments& args) {
if (r) {
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -436,7 +406,6 @@ Local<Object> AddressToJS(const sockaddr* addr) {
static Persistent<String> ipv4_sym;
static Persistent<String> ipv6_sym;
- HandleScope scope;
char ip[INET6_ADDRSTRLEN];
const sockaddr_in *a4;
const sockaddr_in6 *a6;
@@ -475,7 +444,7 @@ Local<Object> AddressToJS(const sockaddr* addr) {
info->Set(address_sym, String::Empty());
}
- return scope.Close(info);
+ return info;
}
View
33 src/udp_wrap.cc
@@ -85,8 +85,6 @@ void UDPWrap::Initialize(Handle<Object> target) {
slab_allocator = new SlabAllocator(SLAB_SIZE);
AtExit(DeleteSlabAllocator, NULL);
- HandleScope scope;
-
buffer_sym = NODE_PSYMBOL("buffer");
oncomplete_sym = NODE_PSYMBOL("oncomplete");
onmessage_sym = NODE_PSYMBOL("onmessage");
@@ -116,16 +114,13 @@ void UDPWrap::Initialize(Handle<Object> target) {
Handle<Value> UDPWrap::New(const Arguments& args) {
- HandleScope scope;
-
assert(args.IsConstructCall());
new UDPWrap(args.This());
- return scope.Close(args.This());
+ return args.This();
}
Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
- HandleScope scope;
int r;
UNWRAP(UDPWrap)
@@ -152,7 +147,7 @@ Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
if (r)
SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
@@ -168,13 +163,12 @@ Handle<Value> UDPWrap::Bind6(const Arguments& args) {
#define X(name, fn) \
Handle<Value> UDPWrap::name(const Arguments& args) { \
- HandleScope scope; \
- UNWRAP(UDPWrap) \
+ UNWRAP(UDPWrap) \
assert(args.Length() == 1); \
int flag = args[0]->Int32Value(); \
int r = fn(&wrap->handle_, flag); \
if (r) SetErrno(uv_last_error(uv_default_loop())); \
- return scope.Close(Integer::New(r)); \
+ return Integer::New(r); \
}
X(SetTTL, uv_udp_set_ttl)
@@ -187,7 +181,6 @@ X(SetMulticastLoopback, uv_udp_set_multicast_loop)
Handle<Value> UDPWrap::SetMembership(const Arguments& args,
uv_membership membership) {
- HandleScope scope;
UNWRAP(UDPWrap)
assert(args.Length() == 2);
@@ -206,7 +199,7 @@ Handle<Value> UDPWrap::SetMembership(const Arguments& args,
if (r)
SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
@@ -221,7 +214,6 @@ Handle<Value> UDPWrap::DropMembership(const Arguments& args) {
Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
- HandleScope scope;
int r;
// send(buffer, offset, length, port, address)
@@ -268,7 +260,7 @@ Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
return Null();
}
else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -284,8 +276,6 @@ Handle<Value> UDPWrap::Send6(const Arguments& args) {
Handle<Value> UDPWrap::RecvStart(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(UDPWrap)
// UV_EALREADY means that the socket is already bound but that's okay
@@ -300,18 +290,15 @@ Handle<Value> UDPWrap::RecvStart(const Arguments& args) {
Handle<Value> UDPWrap::RecvStop(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(UDPWrap)
int r = uv_udp_recv_stop(&wrap->handle_);
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
Handle<Value> UDPWrap::GetSockName(const Arguments& args) {
- HandleScope scope;
struct sockaddr_storage address;
UNWRAP(UDPWrap)
@@ -327,14 +314,12 @@ Handle<Value> UDPWrap::GetSockName(const Arguments& args) {
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
- return scope.Close(AddressToJS(addr));
+ return AddressToJS(addr);
}
// TODO share with StreamWrap::AfterWrite() in stream_wrap.cc
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
- HandleScope scope;
-
assert(req != NULL);
SendWrap* req_wrap = reinterpret_cast<SendWrap*>(req->data);
@@ -371,8 +356,6 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
- HandleScope scope;
-
UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
Local<Object> slab = slab_allocator->Shrink(wrap->object_,
buf.base,

2 comments on commit 23cf4b2

@ry

@mranney, @dshaw, @dannycoates: can you guys test this after you've been running on v0.8 for a while?

@ry

@mranney, @dshaw, @dannycoates: can you guys test this after you've been running on v0.8 for a while?

Please sign in to comment.
Something went wrong with that request. Please try again.