diff --git a/test/parallel/test-tick-processor.js b/test/parallel/test-tick-processor.js new file mode 100644 index 00000000000000..ebcda79d679d55 --- /dev/null +++ b/test/parallel/test-tick-processor.js @@ -0,0 +1,45 @@ +'use strict'; +var fs = require('fs'); +var assert = require('assert'); +var path = require('path'); +var cp = require('child_process'); +var common = require('../common'); + +common.refreshTmpDir(); + +process.chdir(common.tmpDir); +cp.execFileSync(process.execPath, ['-prof', '-pe', + 'function foo(n) {' + + 'require(\'vm\').runInDebugContext(\'Debug\');' + + 'return n < 2 ? n : setImmediate(function() { foo(n-1) + foo(n-2);}); };' + + 'setTimeout(function() { process.exit(0); }, 2000);' + + 'foo(40);']); +var matches = fs.readdirSync(common.tmpDir).filter(function(file) { + return /^isolate-/.test(file); +}); +if (matches.length != 1) { + assert.fail('There should be a single log file.'); +} +var log = matches[0]; +var processor = + path.join(common.testDir, '..', 'tools', 'v8-prof', getScriptName()); +var out = cp.execSync(processor + ' ' + log, {encoding: 'utf8'}); +assert(out.match(/LazyCompile.*foo/)); +if (process.platform === 'win32' || + process.platform === 'sunos' || + process.platform === 'freebsd') { + console.log('1..0 # Skipped: C++ symbols are not mapped for this os.'); + return; +} +assert(out.match(/RunInDebugContext/)); + +function getScriptName() { + switch (process.platform) { + case 'darwin': + return 'mac-tick-processor'; + case 'win32': + return 'windows-tick-processor.bat'; + default: + return 'linux-tick-processor'; + } +} diff --git a/tools/v8-prof/linux-tick-processor b/tools/v8-prof/linux-tick-processor new file mode 100755 index 00000000000000..858405c947fe5e --- /dev/null +++ b/tools/v8-prof/linux-tick-processor @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +umask 077 +TEMP_SCRIPT_FILE="/tmp/node-tick-processor-input-script-$$" +tools_path=`cd $(dirname "$0");pwd` +v8_tools="$tools_path/../../deps/v8/tools" + +cat "$tools_path/polyfill.js" "$v8_tools/splaytree.js" "$v8_tools/codemap.js" \ + "$v8_tools/csvparser.js" "$v8_tools/consarray.js" \ + "$v8_tools/profile.js" "$v8_tools/profile_view.js" \ + "$v8_tools/logreader.js" "$v8_tools/tickprocessor.js" \ + "$v8_tools/SourceMap.js" \ + "$v8_tools/tickprocessor-driver.js" >> "$TEMP_SCRIPT_FILE" + +NODE=${NODE:-node} + +if [ ! -x "$NODE" ] && [ -x "$(dirname "$0")/../../iojs" ]; then + NODE="$(dirname "$0")/../../iojs" +fi + +"$NODE" "$TEMP_SCRIPT_FILE" $@ + +rm -f "$TEMP_SCRIPT_FILE" diff --git a/tools/v8-prof/mac-tick-processor b/tools/v8-prof/mac-tick-processor new file mode 100755 index 00000000000000..968df80c286684 --- /dev/null +++ b/tools/v8-prof/mac-tick-processor @@ -0,0 +1,7 @@ +#!/bin/sh + +# A wrapper script to call 'linux-tick-processor' with Mac-specific settings. + +tools_path=`cd $(dirname "$0");pwd` +v8_tools="$tools_path/../../deps/v8/tools" +"$tools_path/linux-tick-processor" --mac --nm="$v8_tools/mac-nm" $@ diff --git a/tools/v8-prof/polyfill.js b/tools/v8-prof/polyfill.js new file mode 100644 index 00000000000000..0d78391b836d67 --- /dev/null +++ b/tools/v8-prof/polyfill.js @@ -0,0 +1,92 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Node polyfill +var fs = require('fs'); +var os = { + system: function(name, args) { + if (process.platform === 'linux' && name === 'nm') { + // Filter out vdso and vsyscall entries. + var arg = args[args.length - 1]; + if (arg === '[vdso]' || + arg == '[vsyscall]' || + /^[0-9a-f]+-[0-9a-f]+$/.test(arg)) { + return ''; + } + } + return require('child_process').execFileSync( + name, args, {encoding: 'utf8'}); + } +}; +var print = console.log; +function read(fileName) { + return fs.readFileSync(fileName, 'utf8'); +} +arguments = process.argv.slice(2); + +// Polyfill "readline()". +var fd = fs.openSync(arguments[arguments.length - 1], 'r'); +var buf = new Buffer(4096); +var dec = new (require('string_decoder').StringDecoder)('utf-8'); +var line = ''; +versionCheck(); +function readline() { + while (true) { + var lineBreak = line.indexOf('\n'); + if (lineBreak !== -1) { + var res = line.slice(0, lineBreak); + line = line.slice(lineBreak + 1); + return res; + } + var bytes = fs.readSync(fd, buf, 0, buf.length); + line += dec.write(buf.slice(0, bytes)); + if (line.length === 0) { + return false; + } + } +} + +function versionCheck() { + // v8-version looks like "v8-version,$major,$minor,$build,$patch,$candidate" + // whereas process.versions.v8 is either "$major.$minor.$build" or + // "$major.$minor.$build.$patch". + var firstLine = readline(); + line = firstLine + '\n' + line; + firstLine = firstLine.split(','); + var curVer = process.versions.v8.split('.'); + if (firstLine.length !== 6 && firstLine[0] !== 'v8-version') { + console.log('Unable to read v8-version from log file.'); + return; + } + // Compare major, minor and build; ignore the patch and candidate fields. + for (var i = 0; i < 3; i++) { + if (curVer[i] !== firstLine[i + 1]) { + console.log('Testing v8 version different from logging version'); + return; + } + } +} diff --git a/tools/v8-prof/windows-tick-processor.bat b/tools/v8-prof/windows-tick-processor.bat new file mode 100755 index 00000000000000..83e6dde6b76b05 --- /dev/null +++ b/tools/v8-prof/windows-tick-processor.bat @@ -0,0 +1,19 @@ +@echo off +setlocal + +SET tools_dir=%~dp0 +SET v8_tools=%tools_dir%..\..\deps\v8\tools\ + +SET temp_script=%TEMP%\node-tick-processor-input-script + +IF NOT DEFINED NODE (SET NODE=node.exe) +%NODE% --version 2> NUL +if %ERRORLEVEL%==9009 (SET NODE=%~dp0\..\..\Release\iojs.exe) + + +type %tools_dir%polyfill.js %v8_tools%splaytree.js %v8_tools%codemap.js^ + %v8_tools%csvparser.js %v8_tools%consarray.js %v8_tools%profile.js^ + %v8_tools%profile_view.js %v8_tools%logreader.js %v8_tools%SourceMap.js^ + %v8_tools%tickprocessor.js %v8_tools%tickprocessor-driver.js >> %temp_script% +%NODE% %temp_script% --windows %* +del %temp_script%