diff --git a/doc/api/_toc.markdown b/doc/api/_toc.markdown index d5b38b28ed02f1..baa0de2e2b3052 100644 --- a/doc/api/_toc.markdown +++ b/doc/api/_toc.markdown @@ -34,5 +34,6 @@ * [UDP/Datagram](dgram.html) * [URL](url.html) * [Utilities](util.html) +* [V8](v8.html) * [VM](vm.html) * [ZLIB](zlib.html) diff --git a/doc/api/all.markdown b/doc/api/all.markdown index 2a164abb78e98d..9942c8c3b22edf 100644 --- a/doc/api/all.markdown +++ b/doc/api/all.markdown @@ -35,3 +35,4 @@ @include debugger @include cluster @include smalloc +@include v8 diff --git a/doc/api/v8.markdown b/doc/api/v8.markdown new file mode 100644 index 00000000000000..e0b27dc7c25ece --- /dev/null +++ b/doc/api/v8.markdown @@ -0,0 +1,43 @@ +# V8 + + Stability: 1 - Experimental + +This module exposes events and interfaces specific to the version of [V8][] +built with node. These interfaces are subject to change by upstream and are +therefore not covered under the stability index. + +### getHeapStatistics() + +Returns an object with the following properties + +``` +{ + total_heap_size: 7326976, + total_heap_size_executable: 4194304, + total_physical_size: 7326976, + used_heap_size: 3476208, + heap_size_limit: 1535115264 +} +``` + +### setFlagsFromString() + +Set additional V8 command line flags. Use with care; changing settings +after the VM has started may result in unpredictable behavior, including +crashes and data loss. Or it may simply do nothing. + +The V8 options available for a version of node may be determined by running +`iojs --v8-options`. An unofficial, community-maintained list of options +and their effects is available +[here](https://github.com/thlorenz/v8-flags/blob/master/flags-0.11.md). + +Usage: + +``` +// Print GC events to stdout for one minute. +var v8 = require('v8'); +v8.setFlagsFromString('--trace_gc'); +setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3); +``` + +[V8]: https://code.google.com/p/v8/ diff --git a/lib/repl.js b/lib/repl.js index 2b34a1a8c3ac1e..2f47163086ceb9 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -74,7 +74,8 @@ exports.writer = util.inspect; exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', - 'string_decoder', 'tls', 'tty', 'url', 'util', 'vm', 'zlib', 'smalloc']; + 'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib', + 'smalloc']; function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) { diff --git a/lib/v8.js b/lib/v8.js new file mode 100644 index 00000000000000..53b3b0094c89d7 --- /dev/null +++ b/lib/v8.js @@ -0,0 +1,41 @@ +// Copyright (c) 2014, StrongLoop Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +'use strict'; + +var EventEmitter = require('events'); +var v8binding = process.binding('v8'); + +var v8 = module.exports = new EventEmitter(); +v8.getHeapStatistics = v8binding.getHeapStatistics; +v8.setFlagsFromString = v8binding.setFlagsFromString; + + +function emitGC(before, after) { + v8.emit('gc', before, after); +} + + +v8.on('newListener', function(name) { + if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) { + v8binding.startGarbageCollectionTracking(emitGC); + } +}); + + +v8.on('removeListener', function(name) { + if (name === 'gc' && EventEmitter.listenerCount(this, name) === 0) { + v8binding.stopGarbageCollectionTracking(); + } +}); diff --git a/node.gyp b/node.gyp index 5a9afa019e19aa..be266825bf7293 100644 --- a/node.gyp +++ b/node.gyp @@ -64,6 +64,7 @@ 'lib/tty.js', 'lib/url.js', 'lib/util.js', + 'lib/v8.js', 'lib/vm.js', 'lib/zlib.js', ], diff --git a/test/simple/test-v8-flags.js b/test/simple/test-v8-flags.js new file mode 100644 index 00000000000000..1397d8bedd46a5 --- /dev/null +++ b/test/simple/test-v8-flags.js @@ -0,0 +1,26 @@ +// Copyright (c) 2014, StrongLoop Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var v8 = require('v8'); +var vm = require('vm'); + +v8.setFlagsFromString('--allow_natives_syntax'); +assert(eval('%_IsSmi(42)')); +assert(vm.runInThisContext('%_IsSmi(42)')); + +v8.setFlagsFromString('--noallow_natives_syntax'); +assert.throws(function() { eval('%_IsSmi(42)') }, SyntaxError); +assert.throws(function() { vm.runInThisContext('%_IsSmi(42)') }, SyntaxError); diff --git a/test/simple/test-v8-gc.js b/test/simple/test-v8-gc.js new file mode 100644 index 00000000000000..4bce8099d8b6c6 --- /dev/null +++ b/test/simple/test-v8-gc.js @@ -0,0 +1,46 @@ +// Copyright (c) 2014, StrongLoop Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// Flags: --expose_gc + +var common = require('../common'); +var assert = require('assert'); +var v8 = require('v8'); + +assert(typeof gc === 'function', 'Run this test with --expose_gc.'); + +var ncalls = 0; +var before; +var after; + +function ongc(before_, after_) { + // Try very hard to not create garbage because that could kick off another + // garbage collection cycle. + before = before_; + after = after_; + ncalls += 1; +} + +gc(); +v8.on('gc', ongc); +gc(); +v8.removeListener('gc', ongc); +gc(); + +assert.equal(ncalls, 1); +assert.equal(typeof before, 'object'); +assert.equal(typeof after, 'object'); +assert.equal(typeof before.timestamp, 'number'); +assert.equal(typeof after.timestamp, 'number'); +assert.equal(before.timestamp <= after.timestamp, true); diff --git a/test/simple/test-v8-stats.js b/test/simple/test-v8-stats.js new file mode 100644 index 00000000000000..d4623363a5e1a7 --- /dev/null +++ b/test/simple/test-v8-stats.js @@ -0,0 +1,29 @@ +// Copyright (c) 2014, StrongLoop Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var v8 = require('v8'); + +var s = v8.getHeapStatistics(); +var keys = [ + 'heap_size_limit', + 'total_heap_size', + 'total_heap_size_executable', + 'total_physical_size', + 'used_heap_size']; +assert.deepEqual(Object.keys(s).sort(), keys); +keys.forEach(function(key) { + assert.equal(typeof s[key], 'number'); +});