@@ -211,6 +211,16 @@ parser.add_option("--without-etw",
dest="without_etw",
help="Build without ETW")

parser.add_option("--with-perfctr",
action="store_true",
dest="with_perfctr",
help="Build with performance counters (default is true on Windows)")

parser.add_option("--without-perfctr",
action="store_true",
dest="without_perfctr",
help="Build without performance counters")

# CHECKME does this still work with recent releases of V8?
parser.add_option("--gdb",
action="store_true",
@@ -454,7 +464,7 @@ def configure_node(o):
o['variables']['node_use_systemtap'] = b(options.with_dtrace)
if options.systemtap_includes:
o['include_dirs'] += [options.systemtap_includes]
elif b(options.with_dtrace) == 'true':
elif options.with_dtrace:
raise Exception(
'DTrace is currently only supported on SunOS or Linux systems.')
else:
@@ -467,11 +477,19 @@ def configure_node(o):
# By default, enable ETW on Windows.
if sys.platform.startswith('win32'):
o['variables']['node_use_etw'] = b(not options.without_etw);
elif b(options.with_etw) == 'true':
elif options.with_etw:
raise Exception('ETW is only supported on Windows.')
else:
o['variables']['node_use_etw'] = 'false'

# By default, enable Performance counters on Windows.
if sys.platform.startswith('win32'):
o['variables']['node_use_perfctr'] = b(not options.without_perfctr);
elif options.with_perfctr:
raise Exception('Performance counter is only supported on Windows.')
else:
o['variables']['node_use_perfctr'] = 'false'


def configure_libz(o):
o['variables']['node_shared_zlib'] = b(options.shared_zlib)
@@ -841,9 +841,11 @@ OutgoingMessage.prototype._finish = function() {
assert(this.connection);
if (this instanceof ServerResponse) {
DTRACE_HTTP_SERVER_RESPONSE(this.connection);
COUNTER_HTTP_SERVER_RESPONSE();
} else {
assert(this instanceof ClientRequest);
DTRACE_HTTP_CLIENT_REQUEST(this, this.connection);
COUNTER_HTTP_CLIENT_REQUEST();
}
this.emit('finish');
};
@@ -1472,6 +1474,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) {


DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
COUNTER_HTTP_CLIENT_RESPONSE();
req.emit('response', res);
req.res = res;
res.req = req;
@@ -1779,6 +1782,7 @@ function connectionListener(socket) {
debug('server response shouldKeepAlive: ' + shouldKeepAlive);
res.shouldKeepAlive = shouldKeepAlive;
DTRACE_HTTP_SERVER_REQUEST(req, socket);
COUNTER_HTTP_SERVER_REQUEST();

if (socket._httpMessage) {
// There are already pending outgoing res, append.
@@ -361,6 +361,7 @@ Socket.prototype._destroy = function(exception, cb) {
this.destroyed = true;

if (this.server) {
COUNTER_NET_SERVER_CONNECTION_CLOSE(this);
this.server._connections--;
if (this.server._emitCloseIfDrained) {
this.server._emitCloseIfDrained();
@@ -1054,6 +1055,7 @@ function onconnection(clientHandle) {
socket.server = self;

DTRACE_NET_SERVER_CONNECTION(socket);
COUNTER_NET_SERVER_CONNECTION(socket);
self.emit('connection', socket);
socket.emit('connect');
}
@@ -59,7 +59,7 @@ if (isWindows) {
// Regex to split a windows path into three parts: [*, device, slash,
// tail] windows-only
var splitDeviceRe =
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/;
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;

// Regex to split the tail part of the above into [*, dir, basename, ext]
var splitTailRe =
@@ -80,6 +80,10 @@ if (isWindows) {
return [device, dir, basename, ext];
};

var normalizeUNCRoot = function(device) {
return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');
}

// path.resolve([from ...], to)
// windows version
exports.resolve = function() {
@@ -138,8 +142,11 @@ if (isWindows) {
}
}

// Replace slashes (in UNC share name) by backslashes
resolvedDevice = resolvedDevice.replace(/\//g, '\\');
// Convert slashes to backslashes when `resolvedDevice` points to an UNC
// root. Also squash multiple slashes into a single one where appropriate.
if (isUnc) {
resolvedDevice = normalizeUNCRoot(resolvedDevice);
}

// At this point the path should be resolved to a full absolute path,
// but handle relative paths to be safe (might happen when process.cwd()
@@ -180,7 +187,10 @@ if (isWindows) {
}

// Convert slashes to backslashes when `device` points to an UNC root.
device = device.replace(/\//g, '\\');
// Also squash multiple slashes into a single one where appropriate.
if (isUnc) {
device = normalizeUNCRoot(device);
}

return device + (isAbsolute ? '\\' : '') + tail;
};
@@ -194,11 +204,21 @@ if (isWindows) {
var paths = Array.prototype.filter.call(arguments, f);
var joined = paths.join('\\');

// Make sure that the joined path doesn't start with two slashes
// - it will be mistaken for an unc path by normalize() -
// unless the paths[0] also starts with two slashes
if (/^[\\\/]{2}/.test(joined) && !/^[\\\/]{2}/.test(paths[0])) {
joined = joined.substr(1);
// Make sure that the joined path doesn't start with two slashes, because
// normalize() will mistake it for an UNC path then.
//
// This step is skipped when it is very clear that the user actually
// intended to point at an UNC path. This is assumed when the first
// non-empty string arguments starts with exactly two slashes followed by
// at least one more non-slash character.
//
// Note that for normalize() to treat a path as an UNC path it needs to
// have at least 2 components, so we don't filter for that here.
// This means that the user can use join to construct UNC paths from
// a server name and a share name; for example:
// path.join('//server', 'share') -> '\\\\server\\share\')
if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) {
joined = joined.replace(/^[\\\/]{2,}/, '\\');
}

return exports.normalize(joined);
@@ -6,6 +6,7 @@
'werror': '',
'node_use_dtrace%': 'false',
'node_use_etw%': 'false',
'node_use_perfctr%': 'false',
'node_shared_v8%': 'false',
'node_shared_zlib%': 'false',
'node_shared_http_parser%': 'false',
@@ -189,6 +190,17 @@
'<(SHARED_INTERMEDIATE_DIR)/node_etw_provider.rc',
]
} ],
[ 'node_use_perfctr=="true"', {
'defines': [ 'HAVE_PERFCTR=1' ],
'dependencies': [ 'node_perfctr' ],
'sources': [
'src/node_win32_perfctr_provider.h',
'src/node_win32_perfctr_provider.cc',
'src/node_counters.cc',
'src/node_counters.h',
'<(SHARED_INTERMEDIATE_DIR)/node_perfctr_provider.rc',
]
} ],
[ 'node_shared_v8=="false"', {
'sources': [
'deps/v8/include/v8.h',
@@ -287,48 +299,61 @@
} ]
]
},
# generate perf counter header and resource files
{
'target_name': 'node_perfctr',
'type': 'none',
'conditions': [
[ 'node_use_perfctr=="true"', {
'actions': [
{
'action_name': 'node_perfctr_man',
'inputs': [ 'src/res/node_perfctr_provider.man' ],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/node_perfctr_provider.h',
'<(SHARED_INTERMEDIATE_DIR)/node_perfctr_provider.rc',
],
'action': [ 'ctrpp <@(_inputs) '
'-o <(SHARED_INTERMEDIATE_DIR)/node_perfctr_provider.h '
'-rc <(SHARED_INTERMEDIATE_DIR)/node_perfctr_provider.rc'
]
},
],
} ]
]
},
{
'target_name': 'node_js2c',
'type': 'none',
'toolsets': ['host'],
'actions': [
{
'action_name': 'node_js2c',

'inputs': [
'<@(library_files)',
'./config.gypi',
],

'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/node_natives.h',
],

# FIXME can the following conditions be shorted by just setting
# macros.py into some variable which then gets included in the
# action?

'conditions': [
[ 'node_use_dtrace=="true"'
' or node_use_etw=="true"'
' or node_use_systemtap=="true"',
[ 'node_use_dtrace=="false"'
' and node_use_etw=="false"'
' and node_use_systemtap=="false"',
{
'action': [
'<(python)',
'tools/js2c.py',
'<@(_outputs)',
'<@(_inputs)',
'inputs': ['src/macros.py']
}
],
}, { # No Dtrace
[ 'node_use_perfctr=="false"', {
'inputs': [ 'src/perfctr_macros.py' ]
}]
],
'action': [
'<(python)',
'tools/js2c.py',
'<@(_outputs)',
'<@(_inputs)',
'src/macros.py'
],
}]
],
},
],
}, # end node_js2c
@@ -428,4 +453,3 @@
}
] # end targets
}

@@ -30,6 +30,9 @@
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
# include "node_dtrace.h"
#endif
#if defined HAVE_PERFCTR
# include "node_counters.h"
#endif

#include <locale.h>
#include <signal.h>
@@ -2314,6 +2317,10 @@ void Load(Handle<Object> process_l) {
InitDTrace(global);
#endif

#if defined HAVE_PERFCTR
InitPerfCounters(global);
#endif

f->Call(global, 1, args);

if (try_catch.HasCaught()) {