diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b045eceb580a8..f89e1c6352554a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,74 @@
 # io.js ChangeLog
 
+## 2015-08-18, Version 3.1.0, @Fishrock123
+
+### Notable changes
+
+* **buffer**: Fixed a couple large memory leaks (Ben Noordhuis) [#2352](https://github.com/nodejs/node/pull/2352).
+* **crypto**:
+  - Fixed a couple of minor memory leaks (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375).
+  - Signing now checks for OpenSSL errors (P.S.V.R) [#2342](https://github.com/nodejs/node/pull/2342). **Note that this may expose previously hidden errors in user code.**
+* **intl**: Intl support using small-icu is now enabled by default in builds (Steven R. Loomis) [#2264](https://github.com/nodejs/node/pull/2264).
+  - [`String#normalize()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) can now be used for unicode normalization.
+  - The [`Intl`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl) object and various `String` and `Number` methods are present, but only support the English locale.
+  - For support of all locales, node must be built with [full-icu](https://github.com/nodejs/node#build-with-full-icu-support-all-locales-supported-by-icu).
+* **tls**: Fixed tls throughput being much lower after an incorrect merge (Fedor Indutny) [#2381](https://github.com/nodejs/node/pull/2381).
+* **tools**: The v8 tick processor now comes bundled with node (Matt Loring) [#2090](https://github.com/nodejs/node/pull/2090).
+  - This can be used by producing performance profiling output by running node with `--perf`, then running your appropriate platform's script on the output as found in [tools/v8-prof](https://github.com/nodejs/node/tree/master/tools/v8-prof).
+* **util**: `util.inspect(obj)` now prints the constructor name of the object if there is one (Christopher Monsanto) [#1935](https://github.com/nodejs/io.js/pull/1935).
+
+### Known issues
+
+See https://github.com/nodejs/io.js/labels/confirmed-bug for complete and current list of known issues.
+
+* Possible remaining post-3.0.0 buffer memory leak(s), details at [#2308](https://github.com/nodejs/node/issues/2308). Mostly fixed in [2781333...8841947](https://github.com/nodejs/node/compare/27813339cf713275fa7bbf2ae497d13b66aa78ce...88419479ccb6384473339f09e5c55f234f4ee194) - [#2352](https://github.com/nodejs/node/pull/2352), and also [6fff0f7...a40ae51](https://github.com/nodejs/node/compare/6fff0f73dc371153507d96ecd5f88c1ddc7780c9...a40ae513bb99ec3f85ea5b864a366bc7552d61f0) - [#2375](https://github.com/nodejs/node/pull/2375).
+* Some problems with unreferenced timers running during `beforeExit` are still to be resolved. See [#1264](https://github.com/nodejs/io.js/issues/1264).
+* Surrogate pair in REPL can freeze terminal. [#690](https://github.com/nodejs/io.js/issues/690)
+* `process.send()` is not synchronous as the docs suggest, a regression introduced in 1.0.2, see [#760](https://github.com/nodejs/io.js/issues/760).
+* Calling `dns.setServers()` while a DNS query is in progress can cause the process to crash on a failed assertion. [#894](https://github.com/nodejs/io.js/issues/894)
+* `url.resolve` may transfer the auth portion of the url when resolving between two full hosts, see [#1435](https://github.com/nodejs/io.js/issues/1435).
+
+### Commits
+
+* [[`3645dc62ed`](https://github.com/nodejs/node/commit/3645dc62ed)] - **build**: work around VS2015 issue in ICU <56 (Steven R. Loomis) [#2283](https://github.com/nodejs/node/pull/2283)
+* [[`1f12e03266`](https://github.com/nodejs/node/commit/1f12e03266)] - **(SEMVER-MINOR)** **build**: intl: converge from joyent/node (Steven R. Loomis) [#2264](https://github.com/nodejs/node/pull/2264)
+* [[`071640abdd`](https://github.com/nodejs/node/commit/071640abdd)] - **build**: Intl: bump ICU4C from 54 to 55 (Steven R. Loomis) [#2293](https://github.com/nodejs/node/pull/2293)
+* [[`07a88b0c8b`](https://github.com/nodejs/node/commit/07a88b0c8b)] - **build**: update manifest to include Windows 10 (Lucien Greathouse) [#2332](https://github.com/nodejs/io.js/pull/2332)
+* [[`0bb099f444`](https://github.com/nodejs/node/commit/0bb099f444)] - **build**: expand ~ in install prefix early (Ben Noordhuis) [#2307](https://github.com/nodejs/io.js/pull/2307)
+* [[`7fe6dd8f5d`](https://github.com/nodejs/node/commit/7fe6dd8f5d)] - **crypto**: check for OpenSSL errors when signing (P.S.V.R) [#2342](https://github.com/nodejs/node/pull/2342)
+* [[`605f6ee904`](https://github.com/nodejs/node/commit/605f6ee904)] - **crypto**: fix memory leak in PBKDF2Request (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`ba6eb8af12`](https://github.com/nodejs/node/commit/ba6eb8af12)] - **crypto**: fix memory leak in ECDH::SetPrivateKey (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`6a16368611`](https://github.com/nodejs/node/commit/6a16368611)] - **crypto**: fix memory leak in PublicKeyCipher::Cipher (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`a760a87803`](https://github.com/nodejs/node/commit/a760a87803)] - **crypto**: fix memory leak in SafeX509ExtPrint (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`f45487cd6e`](https://github.com/nodejs/node/commit/f45487cd6e)] - **crypto**: fix memory leak in SetDHParam (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`2ff183dd86`](https://github.com/nodejs/node/commit/2ff183dd86)] - **doc**: Update FIPS instructions in README.md (Michael Dawson) [#2278](https://github.com/nodejs/node/pull/2278)
+* [[`6483bc2e8f`](https://github.com/nodejs/node/commit/6483bc2e8f)] - **doc**: clarify options for fs.watchFile() (Rich Trott) [#2425](https://github.com/nodejs/node/pull/2425)
+* [[`e76822f454`](https://github.com/nodejs/node/commit/e76822f454)] - **doc**: multiple documentation updates cherry picked from v0.12 (James M Snell) [#2302](https://github.com/nodejs/io.js/pull/2302)
+* [[`1738c9680b`](https://github.com/nodejs/node/commit/1738c9680b)] - **net**: ensure Socket reported address is current (Ryan Graham) [#2095](https://github.com/nodejs/io.js/pull/2095)
+* [[`844d3f0e3e`](https://github.com/nodejs/node/commit/844d3f0e3e)] - **path**: use '===' instead of '==' for comparison (Sam Stites) [#2388](https://github.com/nodejs/node/pull/2388)
+* [[`7118b8a882`](https://github.com/nodejs/node/commit/7118b8a882)] - **path**: remove dead code in favor of unit tests (Nathan Woltman) [#2282](https://github.com/nodejs/io.js/pull/2282)
+* [[`34f2cfa806`](https://github.com/nodejs/node/commit/34f2cfa806)] - **src**: better error message on failed Buffer malloc (Karl Skomski) [#2422](https://github.com/nodejs/node/pull/2422)
+* [[`b196c1da3c`](https://github.com/nodejs/node/commit/b196c1da3c)] - **src**: fix memory leak in DLOpen (Karl Skomski) [#2375](https://github.com/nodejs/node/pull/2375)
+* [[`d1307b2995`](https://github.com/nodejs/node/commit/d1307b2995)] - **src**: don't use fopen() in require() fast path (Ben Noordhuis) [#2377](https://github.com/nodejs/node/pull/2377)
+* [[`455ec570d1`](https://github.com/nodejs/node/commit/455ec570d1)] - **src**: rename Buffer::Use() to Buffer::New() (Ben Noordhuis) [#2352](https://github.com/nodejs/node/pull/2352)
+* [[`fd63e1ce2b`](https://github.com/nodejs/node/commit/fd63e1ce2b)] - **src**: introduce internal Buffer::Copy() function (Ben Noordhuis) [#2352](https://github.com/nodejs/node/pull/2352)
+* [[`5586ceca13`](https://github.com/nodejs/node/commit/5586ceca13)] - **src**: move internal functions out of node_buffer.h (Ben Noordhuis) [#2352](https://github.com/nodejs/node/pull/2352)
+* [[`bff9bcddb6`](https://github.com/nodejs/node/commit/bff9bcddb6)] - **src**: plug memory leaks (Ben Noordhuis) [#2352](https://github.com/nodejs/node/pull/2352)
+* [[`ccf12df4f3`](https://github.com/nodejs/node/commit/ccf12df4f3)] - **(SEMVER-MINOR)** **src**: add total_available_size to v8 statistics (Roman Klauke) [#2348](https://github.com/nodejs/io.js/pull/2348)
+* [[`194eeb841b`](https://github.com/nodejs/node/commit/194eeb841b)] - **test**: drop Isolate::GetCurrent() from addon tests (Ben Noordhuis) [#2427](https://github.com/nodejs/node/pull/2427)
+* [[`46cdb2f6e2`](https://github.com/nodejs/node/commit/46cdb2f6e2)] - **test**: lint addon tests (Ben Noordhuis) [#2427](https://github.com/nodejs/node/pull/2427)
+* [[`850c794882`](https://github.com/nodejs/node/commit/850c794882)] - **test**: refactor test-fs-watchfile.js (Rich Trott) [#2393](https://github.com/nodejs/node/pull/2393)
+* [[`a3160c0a33`](https://github.com/nodejs/node/commit/a3160c0a33)] - **test**: correct spelling of 'childProcess' (muddletoes) [#2389](https://github.com/nodejs/node/pull/2389)
+* [[`e51f90d747`](https://github.com/nodejs/node/commit/e51f90d747)] - **test**: option to run a subset of tests (João Reis) [#2260](https://github.com/nodejs/io.js/pull/2260)
+* [[`cc46d3bca3`](https://github.com/nodejs/node/commit/cc46d3bca3)] - **test**: clarify dropMembership() call (Rich Trott) [#2062](https://github.com/nodejs/io.js/pull/2062)
+* [[`0ee4df9c7a`](https://github.com/nodejs/node/commit/0ee4df9c7a)] - **test**: make listen-fd-cluster/server more robust (Sam Roberts) [#1944](https://github.com/nodejs/io.js/pull/1944)
+* [[`cf9ba81398`](https://github.com/nodejs/node/commit/cf9ba81398)] - **test**: address timing issues in simple http tests (Gireesh Punathil) [#2294](https://github.com/nodejs/io.js/pull/2294)
+* [[`cbb75c4f86`](https://github.com/nodejs/node/commit/cbb75c4f86)] - **tls**: fix throughput issues after incorrect merge (Fedor Indutny) [#2381](https://github.com/nodejs/node/pull/2381)
+* [[`94b765f409`](https://github.com/nodejs/node/commit/94b765f409)] - **tls**: fix check for reused session (Fedor Indutny) [#2312](https://github.com/nodejs/io.js/pull/2312)
+* [[`e83a41ad65`](https://github.com/nodejs/node/commit/e83a41ad65)] - **tls**: introduce internal `onticketkeycallback` (Fedor Indutny) [#2312](https://github.com/nodejs/io.js/pull/2312)
+* [[`fb0f5d733f`](https://github.com/nodejs/node/commit/fb0f5d733f)] - **(SEMVER-MINOR)** **tools**: run the tick processor without building v8 (Matt Loring) [#2090](https://github.com/nodejs/node/pull/2090)
+* [[`7606bdb897`](https://github.com/nodejs/node/commit/7606bdb897)] - **(SEMVER-MINOR)** **util**: display constructor when inspecting objects (Christopher Monsanto) [#1935](https://github.com/nodejs/io.js/pull/1935)
+
 ## 2015-08-04, Version 3.0.0, @rvagg
 
 ### Notable changes
diff --git a/Makefile b/Makefile
index 286b6180a66e11..7027ba973f95c1 100644
--- a/Makefile
+++ b/Makefile
@@ -483,8 +483,19 @@ CPPLINT_EXCLUDE += src/node_win32_perfctr_provider.cc
 CPPLINT_EXCLUDE += src/queue.h
 CPPLINT_EXCLUDE += src/tree.h
 CPPLINT_EXCLUDE += src/v8abbr.h
-
-CPPLINT_FILES = $(filter-out $(CPPLINT_EXCLUDE), $(wildcard src/*.cc src/*.h src/*.c tools/icu/*.h tools/icu/*.cc deps/debugger-agent/include/* deps/debugger-agent/src/*))
+CPPLINT_EXCLUDE += $(wildcard test/addons/doc-*/*.cc test/addons/doc-*/*.h)
+
+CPPLINT_FILES = $(filter-out $(CPPLINT_EXCLUDE), $(wildcard \
+	deps/debugger-agent/include/* \
+	deps/debugger-agent/src/* \
+	src/*.c \
+	src/*.cc \
+	src/*.h \
+	test/addons/*/*.cc \
+	test/addons/*/*.h \
+	tools/icu/*.cc \
+	tools/icu/*.h \
+	))
 
 cpplint:
 	@$(PYTHON) tools/cpplint.py $(CPPLINT_FILES)
diff --git a/README.md b/README.md
index 60e7620fbf33bc..dcf36e4dbcec82 100644
--- a/README.md
+++ b/README.md
@@ -269,20 +269,46 @@ NOTE: Windows is not yet supported
 It is possible to build io.js with
 [OpenSSL FIPS module](https://www.openssl.org/docs/fips/fipsnotes.html).
 
+**Note** that building in this way does **not** allow you to
+claim that the runtime is FIPS 140-2 validated.  Instead you
+can indicate that the runtime uses a validated module.  See
+the [security policy]
+(http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)
+page 60 for more details.  In addition, the validation for
+the underlying module is only valid if it is deployed in
+accordance with its [security policy]
+(http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf).
+If you need FIPS validated cryptography it is recommended that you
+read both the [security policy]
+(http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)
+and [user guide] (https://openssl.org/docs/fips/UserGuide-2.0.pdf).
+
 Instructions:
 
-1. Download and verify `openssl-fips-x.x.x.tar.gz` from
-   https://www.openssl.org/source/
-2. Extract source to `openssl-fips` folder
-3. ``cd openssl-fips && ./config fipscanisterbuild --prefix=`pwd`/out``
-   (NOTE: On OS X, you may want to run
-    ``./Configure darwin64-x86_64-cc --prefix=`pwd`/out`` if you are going to
-    build x64-mode io.js)
-4. `make -j && make install`
-5. Get into io.js checkout folder
-6. `./configure --openssl-fips=/path/to/openssl-fips/out`
-7. Build io.js with `make -j`
-8. Verify with `node -p "process.versions.openssl"` (`1.0.2a-fips`)
+1. Obtain a copy of openssl-fips-x.x.x.tar.gz.
+   To comply with the security policy you must ensure the path
+   through which you get the file complies with the requirements
+   for a "secure intallation" as described in section 6.6 in
+   the [user guide] (https://openssl.org/docs/fips/UserGuide-2.0.pdf).
+   For evaluation/experimentation you can simply download and verify
+   `openssl-fips-x.x.x.tar.gz` from https://www.openssl.org/source/
+2. Extract source to `openssl-fips` folder and `cd openssl-fips`
+3. `./config`
+4. `make`
+5. `make install`
+   (NOTE: to comply with the security policy you must use the exact
+   commands in steps 3-5 without any additional options as per
+   Appendix A in the [security policy]
+   (http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf).
+   The only exception is that `./config no-asm` can be
+   used in place of `./config` )
+6. Get into io.js checkout folder
+7. `./configure --openssl-fips=/path/to/openssl-fips/installdir`
+   For example on ubuntu 12 the installation directory was
+   /usr/local/ssl/fips-2.0
+8. Build io.js with `make -j`
+9. Verify with `node -p "process.versions.openssl"` (`1.0.2a-fips`)
+
 
 ## Resources for Newcomers
 
diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown
index ebc2046d76ac1e..c9fd8466811c14 100644
--- a/doc/api/fs.markdown
+++ b/doc/api/fs.markdown
@@ -557,11 +557,12 @@ The synchronous version of `fs.appendFile`. Returns `undefined`.
 Watch for changes on `filename`. The callback `listener` will be called each
 time the file is accessed.
 
-The second argument is optional. The `options` if provided should be an object
-containing two members a boolean, `persistent`, and `interval`. `persistent`
-indicates whether the process should continue to run as long as files are
-being watched. `interval` indicates how often the target should be polled,
-in milliseconds. The default is `{ persistent: true, interval: 5007 }`.
+The `options` argument may be omitted. If provided, it should be an object. The
+`options` object may contain a boolean named `persistent` that indicates
+whether the process should continue to run as long as files are being watched.
+The `options` object may specify an `interval` property indicating how often the
+target should be polled in milliseconds. The default is
+`{ persistent: true, interval: 5007 }`.
 
 The `listener` gets two arguments the current stat object and the previous
 stat object:
diff --git a/lib/path.js b/lib/path.js
index 78c61579ec0fc8..4bcb2b3672091c 100644
--- a/lib/path.js
+++ b/lib/path.js
@@ -277,7 +277,7 @@ win32.relative = function(from, to) {
     }
   }
 
-  if (samePartsLength == 0) {
+  if (samePartsLength === 0) {
     return to;
   }
 
diff --git a/src/node.cc b/src/node.cc
index c272139e5518cd..e1ca866f869d10 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -2124,6 +2124,7 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
 
   if (is_dlopen_error) {
     Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
+    uv_dlclose(&lib);
 #ifdef _WIN32
     // Windows needs to add the filename into the error message
     errmsg = String::Concat(errmsg, args[1]->ToString(env->isolate()));
@@ -2133,10 +2134,12 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
   }
 
   if (mp == nullptr) {
+    uv_dlclose(&lib);
     env->ThrowError("Module did not self-register.");
     return;
   }
   if (mp->nm_version != NODE_MODULE_VERSION) {
+    uv_dlclose(&lib);
     char errmsg[1024];
     snprintf(errmsg,
              sizeof(errmsg),
@@ -2146,6 +2149,7 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
     return;
   }
   if (mp->nm_flags & NM_F_BUILTIN) {
+    uv_dlclose(&lib);
     env->ThrowError("Built-in module self-registered.");
     return;
   }
@@ -2162,6 +2166,7 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
   } else if (mp->nm_register_func != nullptr) {
     mp->nm_register_func(exports, module, mp->nm_priv);
   } else {
+    uv_dlclose(&lib);
     env->ThrowError("Module has no declared entry point.");
     return;
   }
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
index 76a733311b0eb0..c8be5b5a448c9e 100644
--- a/src/node_buffer.cc
+++ b/src/node_buffer.cc
@@ -408,8 +408,10 @@ void Create(const FunctionCallbackInfo<Value>& args) {
   void* data;
   if (length > 0) {
     data = malloc(length);
-    if (data == nullptr)
-      return env->ThrowRangeError("invalid Buffer length");
+    if (data == nullptr) {
+      return env->ThrowRangeError(
+          "Buffer allocation failed - process out of memory");
+    }
   } else {
     data = nullptr;
   }
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index bf24a9e48e4930..1af462490f096b 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -805,10 +805,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
     return;
 
   const int keylen = BN_num_bits(dh->p);
-  if (keylen < 1024)
+  if (keylen < 1024) {
+    DH_free(dh);
     return env->ThrowError("DH parameter is less than 1024 bits");
-  else if (keylen < 2048)
+  } else if (keylen < 2048) {
     fprintf(stderr, "WARNING: DH parameter is less than 2048 bits\n");
+  }
 
   SSL_CTX_set_options(sc->ctx_, SSL_OP_SINGLE_DH_USE);
   int r = SSL_CTX_set_tmp_dh(sc->ctx_, dh);
@@ -1295,6 +1297,7 @@ static bool SafeX509ExtPrint(BIO* out, X509_EXTENSION* ext) {
       if (nval == NULL)
         return false;
       X509V3_EXT_val_prn(out, nval, 0, 0);
+      sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
     }
   }
   sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
@@ -3580,7 +3583,11 @@ SignBase::Error Sign::SignFinal(const char* key_pem,
                                  nullptr,
                                  CryptoPemCallback,
                                  const_cast<char*>(passphrase));
-  if (pkey == nullptr)
+
+  // Errors might be injected into OpenSSL's error stack
+  // without `pkey` being set to nullptr;
+  // cf. the test of `test_bad_rsa_privkey.pem` for an example.
+  if (pkey == nullptr || 0 != ERR_peek_error())
     goto exit;
 
   if (EVP_SignFinal(&mdctx_, *sig, sig_len, pkey))
@@ -3628,6 +3635,9 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
   md_len = 8192;  // Maximum key size is 8192 bits
   md_value = new unsigned char[md_len];
 
+  ClearErrorOnReturn clear_error_on_return;
+  (void) &clear_error_on_return;  // Silence compiler warning.
+
   Error err = sign->SignFinal(
       buf,
       buf_len,
@@ -3928,6 +3938,8 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
   fatal = false;
 
  exit:
+  if (x509 != nullptr)
+    X509_free(x509);
   if (pkey != nullptr)
     EVP_PKEY_free(pkey);
   if (bp != nullptr)
@@ -3960,6 +3972,9 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
   unsigned char* out_value = nullptr;
   size_t out_len = 0;
 
+  ClearErrorOnReturn clear_error_on_return;
+  (void) &clear_error_on_return;  // Silence compiler warning.
+
   bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
       kbuf,
       klen,
@@ -4563,8 +4578,12 @@ void ECDH::SetPrivateKey(const FunctionCallbackInfo<Value>& args) {
   if (priv == nullptr)
     return env->ThrowError("Failed to convert Buffer to BN");
 
-  if (!EC_KEY_set_private_key(ecdh->key_, priv))
+  int result = EC_KEY_set_private_key(ecdh->key_, priv);
+  BN_free(priv);
+
+  if (!result) {
     return env->ThrowError("Failed to convert BN to a private key");
+  }
 }
 
 
@@ -4613,6 +4632,7 @@ class PBKDF2Request : public AsyncWrap {
   }
 
   ~PBKDF2Request() override {
+    release();
     persistent().Reset();
   }
 
@@ -4654,10 +4674,15 @@ class PBKDF2Request : public AsyncWrap {
 
   inline void release() {
     free(pass_);
+    pass_ = nullptr;
     passlen_ = 0;
+
     free(salt_);
+    salt_ = nullptr;
     saltlen_ = 0;
+
     free(key_);
+    key_ = nullptr;
     keylen_ = 0;
   }
 
@@ -4728,7 +4753,6 @@ void EIO_PBKDF2After(uv_work_t* work_req, int status) {
   Local<Value> argv[2];
   EIO_PBKDF2After(req, argv);
   req->MakeCallback(env->ondone_string(), ARRAY_SIZE(argv), argv);
-  req->release();
   delete req;
 }
 
@@ -4839,6 +4863,9 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
     Local<Value> argv[2];
     EIO_PBKDF2(req);
     EIO_PBKDF2After(req, argv);
+
+    delete req;
+
     if (argv[0]->IsObject())
       env->isolate()->ThrowException(argv[0]);
     else
diff --git a/src/node_file.cc b/src/node_file.cc
index 0297b08e68d478..5eacf9a68d19a4 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -442,31 +442,48 @@ Local<Value> BuildStatsObject(Environment* env, const uv_stat_t* s) {
 // comes from not creating Error objects on failure.
 static void InternalModuleReadFile(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
+  uv_loop_t* loop = env->event_loop();
 
   CHECK(args[0]->IsString());
   node::Utf8Value path(env->isolate(), args[0]);
 
-  FILE* const stream = fopen(*path, "rb");
-  if (stream == nullptr) {
+  uv_fs_t open_req;
+  const int fd = uv_fs_open(loop, &open_req, *path, O_RDONLY, 0, nullptr);
+  uv_fs_req_cleanup(&open_req);
+
+  if (fd < 0) {
     return;
   }
 
   std::vector<char> chars;
-  while (!ferror(stream)) {
+  int64_t offset = 0;
+  for (;;) {
     const size_t kBlockSize = 32 << 10;
     const size_t start = chars.size();
     chars.resize(start + kBlockSize);
-    const size_t numchars = fread(&chars[start], 1, kBlockSize, stream);
-    if (numchars < kBlockSize) {
+
+    uv_buf_t buf;
+    buf.base = &chars[start];
+    buf.len = kBlockSize;
+
+    uv_fs_t read_req;
+    const ssize_t numchars =
+        uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr);
+    uv_fs_req_cleanup(&read_req);
+
+    CHECK_GE(numchars, 0);
+    if (static_cast<size_t>(numchars) < kBlockSize) {
       chars.resize(start + numchars);
     }
     if (numchars == 0) {
       break;
     }
+    offset += numchars;
   }
 
-  CHECK_EQ(false, ferror(stream));
-  CHECK_EQ(0, fclose(stream));
+  uv_fs_t close_req;
+  CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr));
+  uv_fs_req_cleanup(&close_req);
 
   size_t start = 0;
   if (chars.size() >= 3 && 0 == memcmp(&chars[0], "\xEF\xBB\xBF", 3)) {
diff --git a/src/node_version.h b/src/node_version.h
index cf259469de4293..08ca81fa904f7d 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -2,7 +2,7 @@
 #define SRC_NODE_VERSION_H_
 
 #define NODE_MAJOR_VERSION 3
-#define NODE_MINOR_VERSION 0
+#define NODE_MINOR_VERSION 1
 #define NODE_PATCH_VERSION 1
 
 #define NODE_VERSION_IS_RELEASE 0
diff --git a/src/tls_wrap.h b/src/tls_wrap.h
index b906d78de1ffb0..7a9dc888ccb190 100644
--- a/src/tls_wrap.h
+++ b/src/tls_wrap.h
@@ -53,7 +53,7 @@ class TLSWrap : public crypto::SSLWrap<TLSWrap>,
   size_t self_size() const override { return sizeof(*this); }
 
  protected:
-  static const int kClearOutChunkSize = 1024;
+  static const int kClearOutChunkSize = 16384;
 
   // Maximum number of bytes for hello parser
   static const int kMaxHelloLength = 16384;
diff --git a/test/addons/async-hello-world/binding.cc b/test/addons/async-hello-world/binding.cc
index f458dc6a5632fd..aee3a3763f4755 100644
--- a/test/addons/async-hello-world/binding.cc
+++ b/test/addons/async-hello-world/binding.cc
@@ -3,35 +3,34 @@
 #include <v8.h>
 #include <uv.h>
 
-using namespace v8;
-using namespace node;
-
 struct async_req {
   uv_work_t req;
   int input;
   int output;
-  Persistent<Function> callback;
+  v8::Isolate* isolate;
+  v8::Persistent<v8::Function> callback;
 };
 
 void DoAsync(uv_work_t* r) {
   async_req* req = reinterpret_cast<async_req*>(r->data);
-  sleep(1); // simulate CPU intensive process...
+  sleep(1);  // Simulate CPU intensive process...
   req->output = req->input * 2;
 }
 
 void AfterAsync(uv_work_t* r) {
-  Isolate* isolate = Isolate::GetCurrent();
-  HandleScope scope(isolate);
   async_req* req = reinterpret_cast<async_req*>(r->data);
+  v8::Isolate* isolate = req->isolate;
+  v8::HandleScope scope(isolate);
 
-  Handle<Value> argv[2] = {
-    Null(isolate),
-    Integer::New(isolate, req->output)
+  v8::Handle<v8::Value> argv[2] = {
+    v8::Null(isolate),
+    v8::Integer::New(isolate, req->output)
   };
 
-  TryCatch try_catch;
+  v8::TryCatch try_catch(isolate);
 
-  Local<Function> callback = Local<Function>::New(isolate, req->callback);
+  v8::Local<v8::Function> callback =
+      v8::Local<v8::Function>::New(isolate, req->callback);
   callback->Call(isolate->GetCurrentContext()->Global(), 2, argv);
 
   // cleanup
@@ -39,21 +38,22 @@ void AfterAsync(uv_work_t* r) {
   delete req;
 
   if (try_catch.HasCaught()) {
-    FatalException(isolate, try_catch);
+    node::FatalException(isolate, try_catch);
   }
 }
 
-void Method(const FunctionCallbackInfo<Value>& args) {
-  Isolate* isolate = Isolate::GetCurrent();
-  HandleScope scope(isolate);
+void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope scope(isolate);
 
   async_req* req = new async_req;
   req->req.data = req;
 
   req->input = args[0]->IntegerValue();
   req->output = 0;
+  req->isolate = isolate;
 
-  Local<Function> callback = Local<Function>::Cast(args[1]);
+  v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
   req->callback.Reset(isolate, callback);
 
   uv_queue_work(uv_default_loop(),
@@ -62,7 +62,7 @@ void Method(const FunctionCallbackInfo<Value>& args) {
                 (uv_after_work_cb)AfterAsync);
 }
 
-void init(Handle<Object> exports, Handle<Object> module) {
+void init(v8::Handle<v8::Object> exports, v8::Handle<v8::Object> module) {
   NODE_SET_METHOD(module, "exports", Method);
 }
 
diff --git a/test/addons/at-exit/binding.cc b/test/addons/at-exit/binding.cc
index 156dbe4ff54bb8..d300aad3e8256f 100644
--- a/test/addons/at-exit/binding.cc
+++ b/test/addons/at-exit/binding.cc
@@ -16,12 +16,10 @@ static int at_exit_cb1_called = 0;
 static int at_exit_cb2_called = 0;
 
 static void at_exit_cb1(void* arg) {
-  // FIXME(bnoordhuis) Isolate::GetCurrent() is on its way out.
-  Isolate* isolate = Isolate::GetCurrent();
+  Isolate* isolate = static_cast<Isolate*>(arg);
   HandleScope handle_scope(isolate);
-  assert(arg == 0);
   Local<Object> obj = Object::New(isolate);
-  assert(!obj.IsEmpty()); // assert VM is still alive
+  assert(!obj.IsEmpty());  // Assert VM is still alive.
   assert(obj->IsObject());
   at_exit_cb1_called++;
 }
@@ -37,7 +35,7 @@ static void sanity_check(void) {
 }
 
 void init(Handle<Object> target) {
-  AtExit(at_exit_cb1);
+  AtExit(at_exit_cb1, target->CreationContext()->GetIsolate());
   AtExit(at_exit_cb2, cookie);
   AtExit(at_exit_cb2, cookie);
   atexit(sanity_check);
diff --git a/test/addons/hello-world-function-export/binding.cc b/test/addons/hello-world-function-export/binding.cc
index 91fc26cef652fb..68db22748fdbd3 100644
--- a/test/addons/hello-world-function-export/binding.cc
+++ b/test/addons/hello-world-function-export/binding.cc
@@ -1,15 +1,13 @@
 #include <node.h>
 #include <v8.h>
 
-using namespace v8;
-
-void Method(const FunctionCallbackInfo<Value>& args) {
-  Isolate* isolate = Isolate::GetCurrent();
-  HandleScope scope(isolate);
-  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
+void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope scope(isolate);
+  args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world"));
 }
 
-void init(Handle<Object> exports, Handle<Object> module) {
+void init(v8::Handle<v8::Object> exports, v8::Handle<v8::Object> module) {
   NODE_SET_METHOD(module, "exports", Method);
 }
 
diff --git a/test/addons/hello-world/binding.cc b/test/addons/hello-world/binding.cc
index 1a6d179abe264b..4982bc3e55d84a 100644
--- a/test/addons/hello-world/binding.cc
+++ b/test/addons/hello-world/binding.cc
@@ -1,15 +1,13 @@
 #include <node.h>
 #include <v8.h>
 
-using namespace v8;
-
-void Method(const FunctionCallbackInfo<Value>& args) {
-  Isolate* isolate = Isolate::GetCurrent();
-  HandleScope scope(isolate);
-  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
+void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope scope(isolate);
+  args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world"));
 }
 
-void init(Handle<Object> target) {
+void init(v8::Handle<v8::Object> target) {
   NODE_SET_METHOD(target, "hello", Method);
 }
 
diff --git a/test/fixtures/test_bad_rsa_privkey.pem b/test/fixtures/test_bad_rsa_privkey.pem
new file mode 100644
index 00000000000000..cc84a6fc6d67de
--- /dev/null
+++ b/test/fixtures/test_bad_rsa_privkey.pem
@@ -0,0 +1,10 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAz0ZHmXyxQSdWk6NF
+GRotTax0O94iHv843su0mOynV9QLvlAwMrUk9k4+/SwyLu0eE3iYsYgXstXi3t2u
+rDSIMwIDAQABAkAH4ag/Udp7m79TBdZOygwG9BPHYv7xJstGzYAkgHssf7Yd5ZuC
+hpKtBvWdPXZaAFbwF8NSisMl98Q/9zgB/q5BAiEA5zXuwMnwt4hE2YqzBDRFB4g9
+I+v+l1soy6x7Wdqo9esCIQDlf15qDb26uRDurBioE3IpZstWIIvLDdKqviZXKMs8
+2QIgWeC5QvA9RtsOCJLGLCg1fUwUmFYwzZ1+Kk6OVMuPSqkCIDIWFSXyL8kzoKVm
+O89axxyQCaqXWcsMDkEjVLzK82gpAiB7lzdDHr7MoMWwV2wC/heEFC2p0Rw4wg9j
+1V8QbL0Q0A==
+-----END RSA PRIVATE KEY-----
diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js
index 55b57e65154700..57191b24ae351a 100644
--- a/test/parallel/test-crypto.js
+++ b/test/parallel/test-crypto.js
@@ -124,5 +124,21 @@ assert.throws(function() {
   crypto.createSign('RSA-SHA256').update('test').sign(priv);
 }, /RSA_sign:digest too big for rsa key/);
 
+assert.throws(function() {
+  // The correct header inside `test_bad_rsa_privkey.pem` should have been
+  // -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----
+  // instead of
+  // -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----
+  // It is generated in this way:
+  //   $ openssl genrsa -out mykey.pem 512;
+  //   $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in mykey.pem \
+  //     -out private_key.pem -nocrypt;
+  //   Then open private_key.pem and change its header and footer.
+  var sha1_privateKey = fs.readFileSync(common.fixturesDir +
+                                        '/test_bad_rsa_privkey.pem', 'ascii');
+  // this would inject errors onto OpenSSL's error stack
+  crypto.createSign('sha1').sign(sha1_privateKey);
+}, /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/);
+
 // Make sure memory isn't released before being returned
 console.log(crypto.randomBytes(16));
diff --git a/test/parallel/test-fs-watchfile.js b/test/parallel/test-fs-watchfile.js
index 35712741f773df..5e075fb056e8bc 100644
--- a/test/parallel/test-fs-watchfile.js
+++ b/test/parallel/test-fs-watchfile.js
@@ -4,7 +4,6 @@ const common = require('../common');
 const fs = require('fs');
 const path = require('path');
 const assert = require('assert');
-const fixtures = path.join(__dirname, '..', 'fixtures');
 
 // Basic usage tests.
 assert.throws(function() {
@@ -19,7 +18,7 @@ assert.throws(function() {
   fs.watchFile(new Object(), function() {});
 }, /Path must be a string/);
 
-const enoentFile = path.join(fixtures, 'non-existent-file');
+const enoentFile = path.join(common.tmpDir, 'non-existent-file');
 const expectedStatObject = new fs.Stats(
     0,                                        // dev
     0,                                        // mode
@@ -37,24 +36,13 @@ const expectedStatObject = new fs.Stats(
     Date.UTC(1970, 0, 1, 0, 0, 0)             // birthtime
 );
 
-function removeTestFile() {
-  try {
-    fs.unlinkSync(enoentFile);
-  } catch (ex) {
-    if (ex.code !== 'ENOENT') {
-      throw ex;
-    }
-  }
-}
-
-// Make sure that the file does not exist, when the test starts
-removeTestFile();
+common.refreshTmpDir();
 
 // If the file initially didn't exist, and gets created at a later point of
 // time, the callback should be invoked again with proper values in stat object
 var fileExists = false;
 
-fs.watchFile(enoentFile, common.mustCall(function(curr, prev) {
+fs.watchFile(enoentFile, {interval: 0}, common.mustCall(function(curr, prev) {
   if (!fileExists) {
     // If the file does not exist, all the fields should be zero and the date
     // fields should be UNIX EPOCH time
@@ -71,8 +59,7 @@ fs.watchFile(enoentFile, common.mustCall(function(curr, prev) {
     // As the file just got created, previous ino value should be lesser than
     // or equal to zero (non-existent file).
     assert(prev.ino <= 0);
-    // Stop watching the file and delete it
+    // Stop watching the file
     fs.unwatchFile(enoentFile);
-    removeTestFile();
   }
 }, 2));
diff --git a/test/parallel/test-require-unicode.js b/test/parallel/test-require-unicode.js
new file mode 100644
index 00000000000000..0bccf06916c326
--- /dev/null
+++ b/test/parallel/test-require-unicode.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('assert');
+const fs = require('fs');
+const path = require('path');
+
+common.refreshTmpDir();
+
+const dirname = path.join(common.tmpDir, '\u4e2d\u6587\u76ee\u5f55');
+fs.mkdirSync(dirname);
+fs.writeFileSync(path.join(dirname, 'file.js'), 'module.exports = 42;');
+fs.writeFileSync(path.join(dirname, 'package.json'),
+                 JSON.stringify({ name: 'test', main: 'file.js' }));
+assert.equal(require(dirname), 42);
+assert.equal(require(path.join(dirname, 'file.js')), 42);
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/test/sequential/test-stdin-from-file.js b/test/sequential/test-stdin-from-file.js
index 35aa5b1a89ac38..07b044769b3791 100644
--- a/test/sequential/test-stdin-from-file.js
+++ b/test/sequential/test-stdin-from-file.js
@@ -2,7 +2,7 @@
 var common = require('../common');
 var assert = require('assert');
 var join = require('path').join;
-var childProccess = require('child_process');
+var childProcess = require('child_process');
 var fs = require('fs');
 
 var stdoutScript = join(common.fixturesDir, 'echo-close-check.js');
@@ -32,7 +32,7 @@ try {
 
 fs.writeFileSync(tmpFile, string);
 
-childProccess.exec(cmd, function(err, stdout, stderr) {
+childProcess.exec(cmd, function(err, stdout, stderr) {
   fs.unlinkSync(tmpFile);
 
   if (err) throw err;
diff --git a/test/sequential/test-stdout-to-file.js b/test/sequential/test-stdout-to-file.js
index 953747688364f7..41b61df4d72bd5 100644
--- a/test/sequential/test-stdout-to-file.js
+++ b/test/sequential/test-stdout-to-file.js
@@ -2,7 +2,7 @@
 var common = require('../common');
 var assert = require('assert');
 var path = require('path');
-var childProccess = require('child_process');
+var childProcess = require('child_process');
 var fs = require('fs');
 
 var scriptString = path.join(common.fixturesDir, 'print-chars.js');
@@ -26,7 +26,7 @@ function test(size, useBuffer, cb) {
 
   common.print(size + ' chars to ' + tmpFile + '...');
 
-  childProccess.exec(cmd, function(err) {
+  childProcess.exec(cmd, function(err) {
     if (err) throw err;
 
     console.log('done!');
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%