├── .eslintignore ├── .gitignore ├── test ├── rimraf-es5.js ├── log-mock.js ├── patches.json └── upload.test.js ├── lib ├── temp-path.js ├── copy-file.js ├── chmod.js ├── bin.js ├── places.js ├── log.js ├── upload.js ├── spawn.js ├── cloud.js ├── thresholds.js ├── system.js ├── verify.js ├── index.js ├── build.js └── github.js ├── places.json ├── readme.md ├── patches ├── backport.R24643.patch ├── backport.R24642.patch ├── backport.R24644.patch ├── backport.R24543.patch ├── backport.PR5159.for.N4.patch ├── patches.json ├── backport.R24523.patch ├── backport.PR5343.for.N0.patch ├── backport.PR5343.for.N4.patch ├── backport.R24262.patch ├── backport.R25444.patch ├── backport.PR4777.for.N0.patch ├── backport.PR4777.for.N4.patch ├── backport.R24824.patch ├── backport.R00000.patch ├── backport.R25039.patch ├── backport.R32768.patch ├── backport.R24266.patch ├── node.v0.12.18.cpp.patch ├── node.v4.9.1.cpp.patch ├── node.v6.17.1.cpp.patch └── node.v10.15.3.cpp.patch ├── license.md └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | /lib-es5 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | /lib-es5 3 | 4 | # dependencies 5 | /node_modules 6 | 7 | # logs 8 | npm-debug.log 9 | -------------------------------------------------------------------------------- /test/rimraf-es5.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const remove = require('fs-extra').remove; 3 | remove(path.join(__dirname, '../lib-es5/*')); 4 | -------------------------------------------------------------------------------- /lib/temp-path.js: -------------------------------------------------------------------------------- 1 | import uniqueTempDir from 'unique-temp-dir'; 2 | 3 | export function tempPath (...args) { 4 | return uniqueTempDir(...args); 5 | } 6 | -------------------------------------------------------------------------------- /places.json: -------------------------------------------------------------------------------- 1 | { 2 | "localPlace": "{tag}/{from}-{nodeVersion}-{platform}-{arch}", 3 | "remotePlace": "uploaded-{tag}-node-{nodeVersion}-{platform}-{arch}" 4 | } 5 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # pkg-fetch 2 | 3 | Github Releases page of this project contains base binaries, 4 | used by `pkg` to create executables. `pkg-fetch` npm package 5 | downloads base binaries or compiles them from source. 6 | -------------------------------------------------------------------------------- /lib/copy-file.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | 3 | export function copyFile (src, dest) { 4 | return fs.copy(src, dest); 5 | } 6 | 7 | export function moveFile (src, dest) { 8 | return fs.move(src, dest); 9 | } 10 | -------------------------------------------------------------------------------- /lib/chmod.js: -------------------------------------------------------------------------------- 1 | import { chmod, stat } from 'fs-extra'; 2 | 3 | export async function plusx (file) { 4 | const s = await stat(file); 5 | const newMode = s.mode | 64 | 8 | 1; 6 | if (s.mode === newMode) return; 7 | const base8 = newMode.toString(8).slice(-3); 8 | await chmod(file, base8); 9 | } 10 | -------------------------------------------------------------------------------- /test/log-mock.js: -------------------------------------------------------------------------------- 1 | class LogMock { 2 | constructor (actions) { 3 | this.actions = actions; 4 | } 5 | 6 | info (text) { 7 | this.actions.push(`> ${text}`); 8 | } 9 | 10 | warn (text) { 11 | this.actions.push(`> WARN ${text}`); 12 | } 13 | 14 | error (text) { 15 | if (text.message) text = text.message; 16 | this.actions.push(`> ERR! ${text}`); 17 | } 18 | 19 | enableProgress () { 20 | } 21 | 22 | showProgress () { 23 | } 24 | 25 | disableProgress () { 26 | } 27 | } 28 | 29 | export default LogMock; 30 | -------------------------------------------------------------------------------- /test/patches.json: -------------------------------------------------------------------------------- 1 | { 2 | "v0.12.15": [ 3 | "backport.R00000.patch", 4 | "backport.R24002.patch", 5 | "backport.R24204.patch", 6 | "backport.R24262.patch", 7 | "backport.R24266.patch", 8 | "backport.R24523.patch", 9 | "backport.R24543.patch", 10 | "backport.R24639.patch", 11 | "backport.R24642.patch", 12 | "backport.R24643.patch", 13 | "backport.R24644.patch", 14 | "backport.R24824.patch", 15 | "backport.R25039.patch", 16 | "backport.R25444.patch", 17 | "node.v0.12.15.patch" 18 | ], 19 | "v4.4.7": [ 20 | "backport.R32768.v8=4.5.patch", 21 | "node.v4.4.7.patch" 22 | ], 23 | "v6.3.1": [ 24 | "node.v6.3.1.patch" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /lib/bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { log } from './log.js'; 4 | import minimist from 'minimist'; 5 | import { need } from './index.js'; 6 | 7 | async function main () { 8 | const argv = minimist(process.argv.slice(2), { 9 | boolean: [ 'f', 'b' ], 10 | string: [ 'n', 'p', 'a' ] 11 | }); 12 | const nodeRange = argv.n || argv._.shift(); 13 | const platform = argv.p || argv._.shift(); 14 | const arch = argv.a || argv._.shift(); 15 | const forceFetch = argv.f; 16 | const forceBuild = argv.b; 17 | const local = await need({ nodeRange, platform, 18 | arch, forceFetch, forceBuild }); 19 | log.info(local); 20 | } 21 | 22 | main().catch((error) => { 23 | if (!error.wasReported) log.error(error); 24 | process.exit(2); 25 | }); 26 | -------------------------------------------------------------------------------- /lib/places.js: -------------------------------------------------------------------------------- 1 | import { major, minor } from 'semver'; 2 | import expandTemplate from 'expand-template'; 3 | import os from 'os'; 4 | import path from 'path'; 5 | import placesJson from '../places.json'; 6 | const expand = expandTemplate(); 7 | 8 | const { PKG_CACHE_PATH } = process.env; 9 | const cachePath = PKG_CACHE_PATH || 10 | path.join(os.homedir(), '.pkg-cache'); 11 | 12 | function tagFromVersion (version) { 13 | const mj = major(version); 14 | const mn = minor(version); 15 | return `v${mj}.${mn}`; 16 | } 17 | 18 | export function localPlace (opts) { 19 | const p = placesJson.localPlace; 20 | const { version } = opts; 21 | const tag = tagFromVersion(version); 22 | Object.assign(opts, { tag }); 23 | const atHome = path.join(cachePath, p); 24 | return expand(path.resolve(atHome), opts); 25 | } 26 | 27 | export function remotePlace (opts) { 28 | const p = placesJson.remotePlace; 29 | const { version } = opts; 30 | const tag = tagFromVersion(version); 31 | Object.assign(opts, { tag }); 32 | return { tag, name: expand(p, opts) }; 33 | } 34 | -------------------------------------------------------------------------------- /patches/backport.R24643.patch: -------------------------------------------------------------------------------- 1 | commit 2577d6c261da26d6fbc97669a3ef8f4b61027c7e 2 | Author: sigurds@chromium.org 3 | Date: Wed Oct 15 14:42:32 2014 +0000 4 | 5 | Fix compilation after r24639 6 | 7 | TBR=yangguo@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/653353003 10 | 11 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24643 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 12 | 13 | diff --git a/src/serialize.h b/src/serialize.h 14 | index 6e1f651..482bc34 100644 15 | --- node/deps/v8/src/serialize.h 16 | +++ node/deps/v8/src/serialize.h 17 | @@ -263,7 +263,8 @@ class Deserializer: public SerializerDeserializer { 18 | void AddReservation(int space, uint32_t chunk) { 19 | DCHECK(space >= 0); 20 | DCHECK(space < kNumberOfSpaces); 21 | - DCHECK(space == LO_SPACE || chunk < Page::kMaxRegularHeapObjectSize); 22 | + DCHECK(space == LO_SPACE || 23 | + chunk < static_cast(Page::kMaxRegularHeapObjectSize)); 24 | Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Zeit, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /patches/backport.R24642.patch: -------------------------------------------------------------------------------- 1 | commit d7acb9148b6407526c257eceaec16c358655a3d5 2 | Author: jkummerow@chromium.org 3 | Date: Wed Oct 15 14:27:26 2014 +0000 4 | 5 | Fix compilation after r24639 6 | 7 | TBR=yangguo@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/661473002 10 | 11 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24642 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 12 | 13 | diff --git a/src/serialize.cc b/src/serialize.cc 14 | index 4c9675e..b980940 100644 15 | --- node/deps/v8/src/serialize.cc 16 | +++ node/deps/v8/src/serialize.cc 17 | @@ -1918,7 +1918,7 @@ uint32_t Serializer::Allocate(int space, int size) { 18 | DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize); 19 | uint32_t new_chunk_size = pending_chunk_[space] + size; 20 | uint32_t allocation; 21 | - if (new_chunk_size > Page::kMaxRegularHeapObjectSize) { 22 | + if (new_chunk_size > static_cast(Page::kMaxRegularHeapObjectSize)) { 23 | // The new chunk size would not fit onto a single page. Complete the 24 | // current chunk and start a new one. 25 | completed_chunks_[space].Add(pending_chunk_[space]); 26 | -------------------------------------------------------------------------------- /patches/backport.R24644.patch: -------------------------------------------------------------------------------- 1 | commit 8949d5f58002c5d058064e9047a6247119e725bf 2 | Author: jkummerow@chromium.org 3 | Date: Wed Oct 15 15:04:09 2014 +0000 4 | 5 | Fix compilation some more after r24639 6 | 7 | Third time's a charm... 8 | 9 | TBR=yangguo@chromium.org 10 | 11 | Review URL: https://codereview.chromium.org/655223003 12 | 13 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24644 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 14 | 15 | diff --git a/src/serialize.cc b/src/serialize.cc 16 | index b980940..4933a19 100644 17 | --- node/deps/v8/src/serialize.cc 18 | +++ node/deps/v8/src/serialize.cc 19 | @@ -2213,7 +2213,9 @@ SerializedCodeData::SerializedCodeData(List* payload, CodeSerializer* cs) 20 | for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { 21 | Vector chunks = cs->FinalAllocationChunks(i); 22 | for (int j = 0; j < chunks.length(); j++) { 23 | - DCHECK(i == LO_SPACE || chunks[j] < Page::kMaxRegularHeapObjectSize); 24 | + DCHECK(i == LO_SPACE || 25 | + chunks[j] < 26 | + static_cast(Page::kMaxRegularHeapObjectSize)); 27 | uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | 28 | IsLastChunkBits::encode(j == chunks.length() - 1); 29 | reservations.Add(chunk); 30 | -------------------------------------------------------------------------------- /patches/backport.R24543.patch: -------------------------------------------------------------------------------- 1 | commit 33dc53f9cc709862de641d32c9a412cf7cfce953 2 | Author: yangguo@chromium.org 3 | Date: Mon Oct 13 07:50:21 2014 +0000 4 | 5 | Always include full reloc info to stubs for serialization. 6 | 7 | R=mvstanton@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/641643006 10 | 11 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24543 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 12 | 13 | diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc 14 | index 80fff3f..63488dc 100644 15 | --- node/deps/v8/src/code-stubs-hydrogen.cc 16 | +++ node/deps/v8/src/code-stubs-hydrogen.cc 17 | @@ -233,6 +233,8 @@ Handle HydrogenCodeStub::GenerateLightweightMissCode( 18 | 19 | // Generate the code for the stub. 20 | masm.set_generating_stub(true); 21 | + // TODO(yangguo): remove this once we can serialize IC stubs. 22 | + masm.enable_serializer(); 23 | NoCurrentFrameScope scope(&masm); 24 | GenerateLightweightMiss(&masm, miss); 25 | } 26 | diff --git a/src/code-stubs.cc b/src/code-stubs.cc 27 | index 357324b..9832650 100644 28 | --- node/deps/v8/src/code-stubs.cc 29 | +++ node/deps/v8/src/code-stubs.cc 30 | @@ -111,6 +111,8 @@ Handle PlatformCodeStub::GenerateCode() { 31 | 32 | // Generate the code for the stub. 33 | masm.set_generating_stub(true); 34 | + // TODO(yangguo): remove this once we can serialize IC stubs. 35 | + masm.enable_serializer(); 36 | NoCurrentFrameScope scope(&masm); 37 | Generate(&masm); 38 | } 39 | -------------------------------------------------------------------------------- /patches/backport.PR5159.for.N4.patch: -------------------------------------------------------------------------------- 1 | From 16b0a8c1acb97a84e9a6e1868d600c525f27b0ec Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= 3 | Date: Mon, 8 Feb 2016 22:36:40 +0100 4 | Subject: src: replace usage of deprecated CompileUnbound 5 | 6 | PR-URL: https://github.com/nodejs/node/pull/5159 7 | Reviewed-By: Ben Noordhuis 8 | 9 | diff --git a/src/node_contextify.cc b/src/node_contextify.cc 10 | index ecf9444..8769b53 100644 11 | --- a/src/node_contextify.cc 12 | +++ b/src/node_contextify.cc 13 | @@ -501,11 +501,11 @@ class ContextifyScript : public BaseObject { 14 | if (source.GetCachedData() != nullptr) 15 | compile_options = ScriptCompiler::kConsumeCodeCache; 16 | else if (produce_cached_data) 17 | compile_options = ScriptCompiler::kProduceCodeCache; 18 | 19 | - Local v8_script = ScriptCompiler::CompileUnbound( 20 | + MaybeLocal v8_script = ScriptCompiler::CompileUnboundScript( 21 | env->isolate(), 22 | &source, 23 | compile_options); 24 | 25 | if (v8_script.IsEmpty()) { 26 | @@ -513,11 +513,12 @@ class ContextifyScript : public BaseObject { 27 | AppendExceptionLine(env, try_catch.Exception(), try_catch.Message()); 28 | } 29 | try_catch.ReThrow(); 30 | return; 31 | } 32 | - contextify_script->script_.Reset(env->isolate(), v8_script); 33 | + contextify_script->script_.Reset(env->isolate(), 34 | + v8_script.ToLocalChecked()); 35 | 36 | if (compile_options == ScriptCompiler::kConsumeCodeCache) { 37 | args.This()->Set( 38 | env->cached_data_rejected_string(), 39 | Boolean::New(env->isolate(), source.GetCachedData()->rejected)); 40 | -------------------------------------------------------------------------------- /patches/patches.json: -------------------------------------------------------------------------------- 1 | { 2 | "v14.4.0": [ 3 | "node.v14.4.0.cpp.patch" 4 | ], 5 | "v14.0.0": [ 6 | "node.v14.0.0.cpp.patch" 7 | ], 8 | "v13.12.0": [ 9 | "node.v13.12.0.cpp.patch" 10 | ], 11 | "v12.18.1": [ 12 | "node.v12.18.1.cpp.patch" 13 | ], 14 | "v12.18.4": [ 15 | "node.v12.18.4.cpp.patch" 16 | ], 17 | "v12.16.1": [ 18 | "node.v12.16.1.cpp.patch" 19 | ], 20 | "v12.13.1": [ 21 | "node.v12.13.1.cpp.patch" 22 | ], 23 | "v12.2.0": [ 24 | "node.v12.2.0.cpp.patch" 25 | ], 26 | "v10.21.0": [ 27 | "node.v10.21.0.cpp.patch" 28 | ], 29 | "v10.17.0": [ 30 | "node.v10.17.0.cpp.patch" 31 | ], 32 | "v10.15.3": [ 33 | "node.v10.15.3.cpp.patch" 34 | ], 35 | "v8.17.0": [ 36 | "node.v8.17.0.cpp.patch" 37 | ], 38 | "v8.16.2": [ 39 | "node.v8.16.2.cpp.patch" 40 | ], 41 | "v8.16.0": [ 42 | "node.v8.16.0.cpp.patch" 43 | ], 44 | "v6.17.1": [ 45 | "node.v6.17.1.cpp.patch" 46 | ], 47 | "v4.9.1": [ 48 | "backport.R32768.patch", 49 | "backport.PR4777.for.N4.patch", 50 | "backport.PR5159.for.N4.patch", 51 | "backport.PR5343.for.N4.patch", 52 | "node.v4.9.1.cpp.patch" 53 | ], 54 | "v0.12.18": [ 55 | "backport.R00000.patch", 56 | "backport.R24002.patch", 57 | "backport.R24204.patch", 58 | "backport.R24262.patch", 59 | "backport.R24266.patch", 60 | "backport.R24523.patch", 61 | "backport.R24543.patch", 62 | "backport.R24639.patch", 63 | "backport.R24642.patch", 64 | "backport.R24643.patch", 65 | "backport.R24644.patch", 66 | "backport.R24824.patch", 67 | "backport.R25039.patch", 68 | "backport.R25444.patch", 69 | "backport.PR4777.for.N0.patch", 70 | "backport.PR5343.for.N0.patch", 71 | "node.v0.12.18.cpp.patch" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /lib/log.js: -------------------------------------------------------------------------------- 1 | import Progress from 'progress'; 2 | import assert from 'assert'; 3 | import chalk from 'chalk'; 4 | 5 | class Log { 6 | _lines (lines) { 7 | if (lines === undefined) return; 8 | if (!Array.isArray(lines)) { 9 | console.log(` ${lines}`); 10 | return; 11 | } 12 | for (const line of lines) { 13 | console.log(` ${line}`); 14 | } 15 | } 16 | 17 | debug (text, lines) { 18 | if (!this.debugMode) return; 19 | console.log(`> ${chalk.green('[debug]')} ${text}`); 20 | this._lines(lines); 21 | } 22 | 23 | info (text, lines) { 24 | console.log(`> ${text}`); 25 | this._lines(lines); 26 | } 27 | 28 | warn (text, lines) { 29 | console.log(`> ${chalk.blue('Warning')} ${text}`); 30 | this._lines(lines); 31 | } 32 | 33 | error (text, lines) { 34 | if (text.stack) text = text.stack; 35 | console.log(`> ${chalk.red('Error!')} ${text}`); 36 | this._lines(lines); 37 | } 38 | 39 | enableProgress (text) { 40 | assert(!this.bar); 41 | text += ' '.repeat(28 - text.length); 42 | this.bar = new Progress(` ${text} [:bar] :percent`, { 43 | stream: process.stdout, 44 | width: 20, 45 | complete: '=', 46 | incomplete: ' ', 47 | total: 100 48 | }); 49 | } 50 | 51 | showProgress (percentage) { 52 | if (!this.bar) return; 53 | this.bar.update(percentage / 100); 54 | } 55 | 56 | disableProgress () { 57 | if (!this.bar) return; 58 | // avoid empty line 59 | if (!this.bar.complete) { 60 | this.bar.terminate(); 61 | } 62 | delete this.bar; 63 | } 64 | } 65 | 66 | export const log = new Log(); 67 | 68 | export function wasReported (error, lines) { 69 | if (error === undefined) { 70 | error = new Error('No message'); 71 | } else 72 | if (typeof error === 'string') { 73 | log.error(error, lines); 74 | error = new Error(error); 75 | } 76 | error.wasReported = true; 77 | return error; 78 | } 79 | -------------------------------------------------------------------------------- /patches/backport.R24523.patch: -------------------------------------------------------------------------------- 1 | commit 6ca8f782aac4df7530d9fd460ec0fabd46628e1d 2 | Author: yangguo@chromium.org 3 | Date: Fri Oct 10 10:51:34 2014 +0000 4 | 5 | Reset code age when serializing code objects. 6 | 7 | R=mvstanton@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/642283002 10 | 11 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24523 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 12 | 13 | diff --git a/src/objects.cc b/src/objects.cc 14 | index 9f25145..3eedfe9 100644 15 | --- node/deps/v8/src/objects.cc 16 | +++ node/deps/v8/src/objects.cc 17 | @@ -10463,6 +10463,12 @@ static Code::Age EffectiveAge(Code::Age age) { 18 | } 19 | 20 | 21 | +void Code::MakeYoung() { 22 | + byte* sequence = FindCodeAgeSequence(); 23 | + if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, GetIsolate()); 24 | +} 25 | + 26 | + 27 | void Code::MakeOlder(MarkingParity current_parity) { 28 | byte* sequence = FindCodeAgeSequence(); 29 | if (sequence != NULL) { 30 | diff --git a/src/objects.h b/src/objects.h 31 | index bcbea12..1faae86 100644 32 | --- node/deps/v8/src/objects.h 33 | +++ node/deps/v8/src/objects.h 34 | @@ -5310,6 +5310,7 @@ class Code: public HeapObject { 35 | // compilation stub. 36 | static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate); 37 | static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate); 38 | + void MakeYoung(); 39 | void MakeOlder(MarkingParity); 40 | static bool IsYoungSequence(Isolate* isolate, byte* sequence); 41 | bool IsOld(); 42 | diff --git a/src/serialize.cc b/src/serialize.cc 43 | index 0cc629d..c287219 100644 44 | --- node/deps/v8/src/serialize.cc 45 | +++ node/deps/v8/src/serialize.cc 46 | @@ -1991,6 +1991,7 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, 47 | return; 48 | // TODO(yangguo): add special handling to canonicalize ICs. 49 | case Code::FUNCTION: 50 | + code_object->MakeYoung(); 51 | SerializeHeapObject(code_object, how_to_code, where_to_point); 52 | return; 53 | } 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pkg-fetch", 3 | "version": "2.6.8", 4 | "description": "Compiles and stores base binaries for pkg", 5 | "main": "lib-es5/index.js", 6 | "license": "MIT", 7 | "repository": "zeit/pkg-fetch", 8 | "bin": { 9 | "pkg-fetch": "lib-es5/bin.js" 10 | }, 11 | "files": [ 12 | "lib-es5/*.js", 13 | "patches/*", 14 | "places.json" 15 | ], 16 | "babel": { 17 | "plugins": [ 18 | "@babel/plugin-transform-async-to-generator", 19 | "@babel/plugin-transform-runtime" 20 | ], 21 | "presets": [ 22 | [ 23 | "@babel/preset-env", 24 | { 25 | "targets": { 26 | "node": "4" 27 | } 28 | } 29 | ] 30 | ] 31 | }, 32 | "dependencies": { 33 | "@babel/runtime": "^7.9.2", 34 | "byline": "^5.0.0", 35 | "chalk": "^3.0.0", 36 | "expand-template": "^2.0.3", 37 | "fs-extra": "^8.1.0", 38 | "minimist": "^1.2.5", 39 | "progress": "^2.0.3", 40 | "request": "^2.88.0", 41 | "request-progress": "^3.0.0", 42 | "semver": "^6.3.0", 43 | "unique-temp-dir": "^1.0.0" 44 | }, 45 | "devDependencies": { 46 | "@babel/cli": "^7.8.4", 47 | "@babel/core": "^7.9.0", 48 | "@babel/plugin-transform-async-to-generator": "^7.8.3", 49 | "@babel/plugin-transform-runtime": "^7.9.0", 50 | "@babel/preset-env": "^7.9.0", 51 | "@babel/register": "^7.9.0", 52 | "ava": "^2.4.0", 53 | "babel-eslint": "^10.1.0", 54 | "eslint": "^6.8.0", 55 | "eslint-config-klopov": "^1.0.2" 56 | }, 57 | "scripts": { 58 | "babel": "node test/rimraf-es5.js && babel lib --out-dir lib-es5", 59 | "bin": "node lib-es5/bin.js", 60 | "lint": "eslint-klopov . || true", 61 | "prepare": "npm run babel", 62 | "prepublishOnly": "eslint-klopov . && npm test", 63 | "start": "node lib-es5/upload.js", 64 | "test": "ava" 65 | }, 66 | "eslintConfig": { 67 | "extends": "klopov", 68 | "parser": "babel-eslint" 69 | }, 70 | "ava": { 71 | "failFast": true, 72 | "files": [ 73 | "test/*.test.js" 74 | ], 75 | "require": [ 76 | "@babel/register" 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /patches/backport.PR5343.for.N0.patch: -------------------------------------------------------------------------------- 1 | From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001 2 | From: Jiho Choi 3 | Date: Sat, 20 Feb 2016 20:44:06 -0600 4 | Subject: vm: fix `produceCachedData` 5 | 6 | Fix segmentation faults when compiling the same code with 7 | `produceCachedData` option. V8 ignores the option when the code is in 8 | its compilation cache and does not return cached data. Added 9 | `cachedDataProduced` property to `v8.Script` to denote whether the 10 | cached data is produced successfully. 11 | 12 | PR-URL: https://github.com/nodejs/node/pull/5343 13 | Reviewed-By: Fedor Indutny 14 | 15 | diff --git a/src/node_contextify.cc b/src/node_contextify.cc 16 | index 1b3d618..dfc51e9 100644 17 | --- a/src/node_contextify.cc 18 | +++ b/src/node_contextify.cc 19 | @@ -527,17 +527,25 @@ class ContextifyScript : public BaseObject { 20 | 21 | if (compile_options == ScriptCompiler::kConsumeCodeCache) { 22 | // no 'rejected' field in cachedData 23 | } else if (compile_options == ScriptCompiler::kProduceCodeCache) { 24 | const ScriptCompiler::CachedData* cached_data = source.GetCachedData(); 25 | - Local buf = Buffer::New( 26 | - env, 27 | - reinterpret_cast(cached_data->data), 28 | - cached_data->length); 29 | - Local cached_data_string = FIXED_ONE_BYTE_STRING( 30 | - args.GetIsolate(), "cachedData"); 31 | - args.This()->Set(cached_data_string, buf); 32 | + bool cached_data_produced = cached_data != NULL; 33 | + if (cached_data_produced) { 34 | + Local buf = Buffer::New( 35 | + env, 36 | + reinterpret_cast(cached_data->data), 37 | + cached_data->length); 38 | + Local cached_data_string = FIXED_ONE_BYTE_STRING( 39 | + args.GetIsolate(), "cachedData"); 40 | + args.This()->Set(cached_data_string, buf); 41 | + } 42 | + Local cached_data_produced_string = FIXED_ONE_BYTE_STRING( 43 | + args.GetIsolate(), "cachedDataProduced"); 44 | + args.This()->Set( 45 | + cached_data_produced_string, 46 | + Boolean::New(env->isolate(), cached_data_produced)); 47 | } 48 | } 49 | 50 | 51 | static bool InstanceOf(Environment* env, const Local& value) { 52 | -------------------------------------------------------------------------------- /lib/upload.js: -------------------------------------------------------------------------------- 1 | import { hostPlatform, targetArchs } from './system.js'; 2 | import { localPlace, remotePlace } from './places.js'; 3 | import { log, wasReported } from './log.js'; 4 | import { Cloud } from './cloud.js'; 5 | import build from './build.js'; 6 | import patchesJson from '../patches/patches.json'; 7 | import path from 'path'; 8 | import { verify } from './verify.js'; 9 | import { version } from '../package.json'; 10 | 11 | const cloud = new Cloud({ owner: 'zeit', repo: 'pkg-fetch' }); 12 | 13 | export function dontBuild (nodeVersion, targetPlatform, targetArch) { 14 | // binaries are not provided for x86 anymore 15 | if (targetPlatform !== 'win' && targetArch === 'x86') return true; 16 | // https://support.apple.com/en-us/HT201948 17 | // don't disable macos-x86 because it is not possible 18 | // to cross-compile for x86 from macos otherwise 19 | const major = nodeVersion.match(/^v?(\d+)/)[1] | 0; 20 | // node 0.12 does not compile on arm 21 | if (/^arm/.test(targetArch) && major === 0) return true; 22 | if (targetPlatform === 'freebsd' && major < 4) return true; 23 | if (targetPlatform === 'alpine' && 24 | (targetArch !== 'x64' || major < 6)) return true; 25 | return false; 26 | } 27 | 28 | export async function main () { 29 | if (!process.env.GITHUB_USERNAME) { 30 | throw wasReported('No github credentials. Upload will fail!'); 31 | } 32 | 33 | for (const nodeVersion in patchesJson) { 34 | for (const targetArch of targetArchs) { 35 | if (dontBuild(nodeVersion, hostPlatform, targetArch)) continue; 36 | const local = localPlace({ from: 'built', arch: targetArch, 37 | nodeVersion, platform: hostPlatform, version }); 38 | const remote = remotePlace({ arch: targetArch, 39 | nodeVersion, platform: hostPlatform, version }); 40 | if (await cloud.alreadyUploaded(remote)) continue; 41 | const short = path.basename(local); 42 | log.info(`Building ${short}...`); 43 | await build(nodeVersion, targetArch, local); 44 | log.info(`Verifying ${short}...`); 45 | await verify(local); 46 | log.info(`Uploading ${short}...`); 47 | try { 48 | await cloud.upload(local, remote); 49 | } catch (error) { 50 | // TODO catch only network errors 51 | if (!error.wasReported) log.error(error); 52 | log.info('Meanwhile i will continue making binaries'); 53 | } 54 | } 55 | } 56 | } 57 | 58 | if (!module.parent) { 59 | main().catch((error) => { 60 | if (!error.wasReported) log.error(error); 61 | process.exit(2); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /lib/spawn.js: -------------------------------------------------------------------------------- 1 | import byline from 'byline'; 2 | import chip from 'child_process'; 3 | import fs from 'fs'; 4 | import { log } from './log.js'; 5 | 6 | const MAX_LINES = 20; 7 | const DEBUG_THRESHOLDS = false; 8 | 9 | function errorLines (lines) { 10 | return lines.slice(-MAX_LINES) 11 | .map((line) => line[1]).join('\n'); 12 | } 13 | 14 | export function spawn (cmd, args, opts) { 15 | const child = chip.spawn(cmd, args, opts); 16 | const stdout = byline(child.stdout); 17 | const stderr = byline(child.stderr); 18 | const lines = []; 19 | 20 | let onData = function (data) { 21 | const time = (new Date()).getTime(); 22 | lines.push([ time, data.toString() ]); // TODO chalk stdout/stderr? 23 | const { thresholds } = this; // eslint-disable-line no-invalid-this 24 | if (thresholds) { 25 | for (const key in thresholds) { 26 | if (data.indexOf(key) >= 0) { 27 | const p = thresholds[key]; 28 | log.showProgress(p); 29 | if (DEBUG_THRESHOLDS) { 30 | lines.push([ time, '************' ]); 31 | lines.push([ time, p + ': ' + key ]); 32 | lines.push([ time, '************' ]); 33 | } 34 | } 35 | } 36 | } 37 | }; 38 | 39 | const promise = new Promise((resolve, reject) => { 40 | child.on('error', (error) => { 41 | console.error(errorLines(lines)); // dont use `log` here 42 | reject(error); 43 | }); 44 | child.on('close', (code) => { 45 | if (code) { 46 | console.error(errorLines(lines)); // dont use `log` here 47 | return reject(new Error(`${cmd} failed with code ${code}`)); 48 | } 49 | resolve(); 50 | }); 51 | }); 52 | 53 | onData = onData.bind(promise); 54 | if (stdout) stdout.on('data', onData); 55 | if (stderr) stderr.on('data', onData); 56 | 57 | promise.child = child; 58 | promise.lines = lines; 59 | return promise; 60 | } 61 | 62 | export function progress (promise, thresholds) { 63 | promise.thresholds = thresholds; 64 | const { child, lines } = promise; 65 | log.enableProgress(promise.child.spawnfile); 66 | log.showProgress(0); 67 | const start = (new Date()).getTime(); 68 | child.on('close', () => { 69 | if (DEBUG_THRESHOLDS) { 70 | const finish = (new Date()).getTime(); 71 | const content = lines.map((line) => 72 | ((100 * (line[0] - start) / (finish - start)) | 0) + ': ' + line[1] 73 | ).join('\n'); 74 | fs.writeFileSync(child.spawnfile + '.debug', content); 75 | } 76 | log.showProgress(100); 77 | log.disableProgress(); 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /lib/cloud.js: -------------------------------------------------------------------------------- 1 | import { mkdirp, remove } from 'fs-extra'; 2 | import { GitHub } from './github.js'; 3 | import assert from 'assert'; 4 | import { moveFile } from './copy-file.js'; 5 | import path from 'path'; 6 | 7 | function uniqueName (name, names) { 8 | if (names.indexOf(name) < 0) return name; 9 | let newName; 10 | let counter = 0; 11 | while (true) { 12 | newName = `${name}-new-${counter}`; 13 | if (names.indexOf(newName) < 0) return newName; 14 | counter += 1; 15 | } 16 | } 17 | 18 | export class Cloud { 19 | constructor ({ owner, repo }) { 20 | this.gh = new GitHub({ owner, repo }); 21 | } 22 | 23 | async _findRelease (tag) { 24 | let release = await this.gh.getRelease(tag); 25 | if (!release) release = await this.gh.getReleaseDraft(tag); 26 | if (!release) release = await this.gh.createRelease(tag); 27 | return release; 28 | } 29 | 30 | async alreadyUploaded (remote) { 31 | const release = await this._findRelease(remote.tag); 32 | return release.assets.some(({ name }) => { 33 | assert(name); 34 | return remote.name === name; 35 | }); 36 | } 37 | 38 | async upload (local, remote) { 39 | const release = await this._findRelease(remote.tag); 40 | const names = release.assets.map(({ name }) => { 41 | assert(name); 42 | return name; 43 | }); 44 | const name = uniqueName(remote.name, names); 45 | await this.gh.uploadAsset(local, release, name); 46 | } 47 | 48 | async uploadMany (items) { 49 | for (const item of items) { 50 | const { local, remote } = item; 51 | await this.upload(local, remote); 52 | } 53 | } 54 | 55 | async download (remote, local) { 56 | const { tag } = remote; 57 | const tempFile = local + '.downloading'; 58 | await mkdirp(path.dirname(tempFile)); 59 | const short = path.basename(local); 60 | const ok = await this.gh.tryDirectly(tag, remote.name, tempFile, short); 61 | if (!ok) { 62 | let release = await this.gh.getRelease(tag); 63 | if (!release) release = await this.gh.getReleaseDraft(tag); 64 | if (!release) return false; 65 | const assets = release.assets.filter(({ name }) => { 66 | assert(name); 67 | return name === remote.name; 68 | }); 69 | if (!assets.length) return false; 70 | assert(assets.length === 1); 71 | const asset = assets[0]; 72 | await this.gh.downloadUrl(asset.url, tempFile, short); 73 | } 74 | await remove(local); 75 | await moveFile(tempFile, local); 76 | await remove(tempFile); 77 | return true; 78 | } 79 | 80 | async downloadMany (items) { 81 | for (const item of items) { 82 | const { remote, local } = item; 83 | await this.download(remote, local); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /patches/backport.PR5343.for.N4.patch: -------------------------------------------------------------------------------- 1 | From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001 2 | From: Jiho Choi 3 | Date: Sat, 20 Feb 2016 20:44:06 -0600 4 | Subject: vm: fix `produceCachedData` 5 | 6 | Fix segmentation faults when compiling the same code with 7 | `produceCachedData` option. V8 ignores the option when the code is in 8 | its compilation cache and does not return cached data. Added 9 | `cachedDataProduced` property to `v8.Script` to denote whether the 10 | cached data is produced successfully. 11 | 12 | PR-URL: https://github.com/nodejs/node/pull/5343 13 | Reviewed-By: Fedor Indutny 14 | 15 | diff --git a/src/env.h b/src/env.h 16 | index 5c99f80..c0b6dcd 100644 17 | --- a/src/env.h 18 | +++ b/src/env.h 19 | @@ -54,10 +54,11 @@ namespace node { 20 | V(buffer_string, "buffer") \ 21 | V(bytes_string, "bytes") \ 22 | V(bytes_parsed_string, "bytesParsed") \ 23 | V(bytes_read_string, "bytesRead") \ 24 | V(cached_data_string, "cachedData") \ 25 | + V(cached_data_produced_string, "cachedDataProduced") \ 26 | V(cached_data_rejected_string, "cachedDataRejected") \ 27 | V(callback_string, "callback") \ 28 | V(change_string, "change") \ 29 | V(oncertcb_string, "oncertcb") \ 30 | V(onclose_string, "_onclose") \ 31 | diff --git a/src/node_contextify.cc b/src/node_contextify.cc 32 | index 8769b53..4f63c20 100644 33 | --- a/src/node_contextify.cc 34 | +++ b/src/node_contextify.cc 35 | @@ -522,15 +522,21 @@ class ContextifyScript : public BaseObject { 36 | args.This()->Set( 37 | env->cached_data_rejected_string(), 38 | Boolean::New(env->isolate(), source.GetCachedData()->rejected)); 39 | } else if (compile_options == ScriptCompiler::kProduceCodeCache) { 40 | const ScriptCompiler::CachedData* cached_data = source.GetCachedData(); 41 | - MaybeLocal buf = Buffer::Copy( 42 | - env, 43 | - reinterpret_cast(cached_data->data), 44 | - cached_data->length); 45 | - args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); 46 | + bool cached_data_produced = cached_data != nullptr; 47 | + if (cached_data_produced) { 48 | + MaybeLocal buf = Buffer::Copy( 49 | + env, 50 | + reinterpret_cast(cached_data->data), 51 | + cached_data->length); 52 | + args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); 53 | + } 54 | + args.This()->Set( 55 | + env->cached_data_produced_string(), 56 | + Boolean::New(env->isolate(), cached_data_produced)); 57 | } 58 | } 59 | 60 | 61 | static bool InstanceOf(Environment* env, const Local& value) { 62 | -------------------------------------------------------------------------------- /lib/thresholds.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable key-spacing */ 2 | /* eslint-disable no-multi-spaces */ 3 | 4 | import assert from 'assert'; 5 | 6 | export default function thresholds (cmd, nodeVersion) { 7 | if (cmd === 'clone') { 8 | return { 9 | 'ving objects: 0%': 0, 'ving objects: 1%': 1, 'ving objects: 6%': 5, 10 | 'ving objects: 12%': 10, 'ving objects: 25%': 20, 'ving objects: 50%': 40, 11 | 'ving objects: 75%': 60, 'deltas: 0%': 80, 'deltas: 50%': 90 12 | }; 13 | } else 14 | if (cmd === 'vcbuild') { 15 | if (/^v?0/.test(nodeVersion)) { 16 | return { 17 | 'http_parser.vcxproj ->': 1, 'openssl.vcxproj ->': 9, 18 | 'v8_base.vcxproj ->': 55, 'mksnapshot.vcxproj ->': 76, 19 | 'node\\Release\\node.exp': 90 20 | }; 21 | } else 22 | if (/^v?4/.test(nodeVersion)) { 23 | return { 24 | 'http_parser.vcxproj ->': 1, 'hydrogen-representation-changes.cc': 13, 25 | 'openssl.vcxproj ->': 21, 'v8_base_0.vcxproj ->': 35, 26 | 'build\\Release\\mksnapshot.lib': 57, 'mksnapshot.vcxproj ->': 67, 27 | 'node\\Release\\node.exp': 85, 'cctest.vcxproj ->': 97 28 | }; 29 | } else 30 | if (/^v?6/.test(nodeVersion)) { 31 | return { 32 | 'http_parser.vcxproj ->': 1, 'openssl.vcxproj ->': 4, 33 | 'icudata.vcxproj ->': 10, 'hydrogen-representation-changes.cc': 15, 34 | 'interface-descriptors-x64.cc': 27, 'v8_base_0.vcxproj ->': 41, 35 | 'build\\Release\\mksnapshot.lib': 55, 'mksnapshot.vcxproj ->': 66, 36 | 'node\\Release\\node.exp': 82, 'cctest.vcxproj ->': 95 37 | }; 38 | } else { 39 | return {}; 40 | } 41 | } else 42 | if (cmd === 'make') { 43 | if (/^v?0/.test(nodeVersion)) { 44 | return { 45 | 'openssl/crypto/ex_data.o.d.raw': 10, 'v8/src/api.o.d.raw': 20, 46 | 'v8/src/compiler/js-graph.o.d.raw': 30, 'v8/src/debug.o.d.raw': 40, 47 | 'v8/src/heap/spaces.o.d.raw': 50, 'v8/src/hydrogen-sce.o.d.raw': 60, 48 | 'v8/src/parser.o.d.raw': 70, 'v8/src/token.o.d.raw': 80, 49 | 'v8/src/x64/stub-cache-x64.o.d.raw': 90 50 | }; 51 | } else 52 | if (/^v?4/.test(nodeVersion)) { 53 | return { 54 | 'v8/src/compiler/code-generator.o.d.raw': 10, 'v8/src/compiler/operator.o.d.raw': 20, 55 | 'v8/src/factory.o.d.raw': 30, 'v8/src/hydrogen.o.d.raw': 40, 56 | 'v8/src/liveedit.o.d.raw': 50, 'v8/src/runtime/runtime-function.o.d.raw': 60, 57 | 'v8/src/v8.o.d.raw': 70, 'v8_nosnapshot/gen/libraries.o.d.raw': 80, 58 | 'openssl/crypto/ex_data.o.d.raw': 90 59 | }; 60 | } else 61 | if (/^v?6/.test(nodeVersion)) { 62 | return { 63 | 'icuucx/deps/icu-small/source/common/parsepos.o.d.raw': 10, 'v8/src/api.o.d.raw': 20, 64 | 'v8/src/compiler/graph-replay.o.d.raw': 30, 'v8/src/compiler.o.d.raw': 40, 65 | 'v8/src/date.o.d.raw': 50, 'v8/src/isolate.o.d.raw': 60, 66 | 'v8/src/runtime/runtime-function.o.d.raw': 70, 'v8/src/x64/assembler-x64.o.d.raw': 80, 67 | 'icui18n/deps/icu-small/source/i18n/search.o.d.raw': 90 68 | }; 69 | } else { 70 | return {}; 71 | } 72 | } else { 73 | assert(false); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/system.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { spawnSync } from 'child_process'; 3 | 4 | function getHostAbi () { 5 | return 'm' + process.versions.modules; 6 | } 7 | 8 | export function abiToNodeRange (abi) { 9 | if (/^m?14/.test(abi)) return 'node0.12'; 10 | if (/^m?46/.test(abi)) return 'node4'; 11 | if (/^m?47/.test(abi)) return 'node5'; 12 | if (/^m?48/.test(abi)) return 'node6'; 13 | if (/^m?51/.test(abi)) return 'node7'; 14 | if (/^m?57/.test(abi)) return 'node8'; 15 | if (/^m?59/.test(abi)) return 'node9'; 16 | if (/^m?64/.test(abi)) return 'node10'; 17 | if (/^m?67/.test(abi)) return 'node11'; 18 | if (/^m?72/.test(abi)) return 'node12'; 19 | if (/^m?79/.test(abi)) return 'node13'; 20 | if (/^m?83/.test(abi)) return 'node14'; 21 | return abi; 22 | } 23 | 24 | export function isValidNodeRange (nodeRange) { 25 | if (nodeRange === 'latest') return true; 26 | if (!(/^node/.test(nodeRange))) return false; 27 | return true; 28 | } 29 | 30 | export function toFancyPlatform (platform) { 31 | if (platform === 'darwin') return 'macos'; 32 | if (platform === 'lin') return 'linux'; 33 | if (platform === 'mac') return 'macos'; 34 | if (platform === 'osx') return 'macos'; 35 | if (platform === 'win32') return 'win'; 36 | if (platform === 'windows') return 'win'; 37 | return platform; 38 | } 39 | 40 | function detectAlpine () { 41 | const { platform } = process; 42 | if (platform !== 'linux') return false; 43 | // https://github.com/sass/node-sass/issues/1589#issuecomment-265292579 44 | const ldd = spawnSync('ldd').stderr.toString(); 45 | if (/\bmusl\b/.test(ldd)) return true; 46 | const lddNode = spawnSync('ldd', [ process.execPath ]).stdout.toString(); 47 | return /\bmusl\b/.test(lddNode); 48 | } 49 | 50 | const isAlpine = detectAlpine(); 51 | 52 | function getHostPlatform () { 53 | const { platform } = process; 54 | if (isAlpine) return 'alpine'; 55 | return toFancyPlatform(platform); 56 | } 57 | 58 | function getKnownPlatforms () { 59 | return [ 'alpine', 'freebsd', 'linux', 'macos', 'win' ]; 60 | } 61 | 62 | export function toFancyArch (arch) { 63 | if (arch === 'ia32') return 'x86'; 64 | if (arch === 'x86_64') return 'x64'; 65 | return arch; 66 | } 67 | 68 | function getArmHostArch () { 69 | const cpu = fs.readFileSync('/proc/cpuinfo', 'utf8'); 70 | if (cpu.indexOf('vfpv3') >= 0) return 'armv7'; 71 | let name = cpu.split('model name')[1]; 72 | if (name) name = name.split(':')[1]; 73 | if (name) name = name.split('\n')[0]; 74 | if (name && name.indexOf('ARMv7') >= 0) return 'armv7'; 75 | return 'armv6'; 76 | } 77 | 78 | function getHostArch () { 79 | const { arch } = process; 80 | if (arch === 'arm') return getArmHostArch(); 81 | return toFancyArch(arch); 82 | } 83 | 84 | function getTargetArchs () { 85 | const arch = getHostArch(); 86 | if (arch === 'x64') return [ 'x64', 'x86' ]; 87 | return [ arch ]; 88 | } 89 | 90 | function getKnownArchs () { 91 | return [ 'x64', 'x86', 'armv6', 'armv7', 'arm64', 'ppc64', 's390x' ]; 92 | } 93 | 94 | export const hostAbi = getHostAbi(); 95 | export const hostPlatform = getHostPlatform(); 96 | export const knownPlatforms = getKnownPlatforms(); 97 | export const hostArch = getHostArch(); 98 | export const targetArchs = getTargetArchs(); 99 | export const knownArchs = getKnownArchs(); 100 | -------------------------------------------------------------------------------- /lib/verify.js: -------------------------------------------------------------------------------- 1 | import { plusx } from './chmod.js'; 2 | import { spawn } from './spawn.js'; 3 | 4 | const script = ` 5 | var vm = require('vm'); 6 | var assert = require('assert'); 7 | var text = '(function () { return 42; })'; 8 | var cd, fn, result; 9 | var modules = process.versions.modules | 0; 10 | var v8 = process.versions.v8.split('.').slice(0, 2).join('.'); 11 | 12 | var s1 = new vm.Script(text, { filename: 's1', produceCachedData: true, sourceless: true }); 13 | assert(s1.cachedDataProduced); 14 | cd = s1.cachedData; 15 | 16 | var kCpuFeaturesOffset, cpuFeatures; 17 | 18 | if (modules === 14) { 19 | } else 20 | if (modules === 46 || modules === 48 || modules === 51) { 21 | kCpuFeaturesOffset = 0x0c; 22 | } else 23 | if (modules === 57) { 24 | if (v8 === '6.2') { 25 | kCpuFeaturesOffset = 0x0c; 26 | } else 27 | if (v8 === '5.8') { 28 | kCpuFeaturesOffset = 0x0c; 29 | } else { 30 | kCpuFeaturesOffset = 0x10; 31 | } 32 | } else 33 | if (modules === 59) { 34 | kCpuFeaturesOffset = 0x0c; 35 | } else 36 | if (modules === 64) { 37 | kCpuFeaturesOffset = 0x0c; 38 | } else 39 | if (modules === 72) { 40 | // no cpu features anymore 41 | } else 42 | if (modules === 79) { 43 | // no cpu features anymore 44 | } else 45 | if (modules === 83) { 46 | // no cpu features anymore 47 | } else { 48 | assert(false, modules); 49 | } 50 | 51 | if (modules >= 46 && // no cpu_features field in 0.12 52 | process.arch !== 'arm' && // non-zero features even in sourceless mode in arm 53 | modules < 72) { // no cpu_features field in 12+ 54 | cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset); 55 | assert(cpuFeatures === 0, 'CPU_FEATURES must be zero'); 56 | } 57 | 58 | var s2 = new vm.Script(undefined, { filename: 's2', cachedData: cd, sourceless: true }); 59 | fn = s2.runInThisContext(); 60 | result = fn(); 61 | assert.equal(result, 42); 62 | 63 | if (modules === 14) { 64 | } else 65 | if (modules === 46 || modules === 48 || 66 | modules === 51 || modules === 57 || modules === 59 || modules === 64) { 67 | var paddedPayloadOffset = 0x48; // see SerializedCodeData::Payload() 68 | var index = paddedPayloadOffset + 10; 69 | cd[index] ^= 0xf0; 70 | var s3 = new vm.Script(undefined, { filename: 's3', cachedData: cd, sourceless: true }); 71 | assert(s3.cachedDataRejected, 's3.cachedDataRejected must be true'); 72 | } else 73 | if (modules === 72) { 74 | } else 75 | if (modules === 79) { 76 | } else 77 | if (modules === 83) { 78 | } else { 79 | assert(false, modules); 80 | } 81 | 82 | var s4 = new vm.Script(text, { filename: 's4', produceCachedData: true }); 83 | assert(s4.cachedDataProduced, 's4.cachedDataProduced must be true'); 84 | cd = s4.cachedData; 85 | 86 | if (modules >= 46 && // no cpu_features field in 0.12 87 | process.arch !== 'arm' && // zero features even in non-sourceless mode in arm 88 | modules < 72) { // no cpu_features field in 12+ 89 | cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset); 90 | assert(cpuFeatures !== 0, 'CPU_FEATURES must be non-zero'); 91 | } 92 | 93 | console.log('ok'); 94 | `; 95 | 96 | export async function verify (local) { 97 | await plusx(local); 98 | await spawn(local, [ '-e', script ], 99 | { env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS' } }); 100 | } 101 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import * as system from './system.js'; 2 | import { abiToNodeRange, hostArch, hostPlatform, // eslint-disable-line no-duplicate-imports 3 | isValidNodeRange, knownArchs, toFancyArch, toFancyPlatform } from './system.js'; 4 | import { localPlace, remotePlace } from './places.js'; 5 | import { log, wasReported } from './log.js'; 6 | import { Cloud } from './cloud.js'; 7 | import build from './build.js'; 8 | import { exists } from 'fs-extra'; 9 | import patchesJson from '../patches/patches.json'; 10 | import path from 'path'; 11 | import semver from 'semver'; 12 | import { version } from '../package.json'; 13 | 14 | const cloud = new Cloud({ owner: 'zeit', repo: 'pkg-fetch' }); 15 | 16 | export async function need (opts = {}) { // eslint-disable-line complexity 17 | let { nodeRange, platform, arch, forceFetch, forceBuild, dryRun } = opts; 18 | if (!nodeRange) throw wasReported('nodeRange not specified'); 19 | if (!platform) throw wasReported('platform not specified'); 20 | if (!arch) throw wasReported('arch not specified'); 21 | 22 | nodeRange = abiToNodeRange(nodeRange); // 'm48' -> 'node6' 23 | if (!isValidNodeRange(nodeRange)) { 24 | throw wasReported('nodeRange must start with \'node\''); 25 | } 26 | if (nodeRange !== 'latest') { 27 | nodeRange = 'v' + nodeRange.slice(4); // 'node6' -> 'v6' for semver 28 | } 29 | 30 | platform = toFancyPlatform(platform); // win32 -> win 31 | arch = toFancyArch(arch); // ia32 -> x86 32 | 33 | function satisfyingNodeVersion () { 34 | const versions = Object.keys(patchesJson) 35 | .filter((nv) => semver.satisfies(nv, nodeRange) || 36 | nodeRange === 'latest') 37 | .sort((nv1, nv2) => (semver.gt(nv1, nv2) ? 1 : -1)); 38 | return versions.pop(); 39 | } 40 | 41 | const nodeVersion = satisfyingNodeVersion(); 42 | if (!nodeVersion) { 43 | throw wasReported(`No available node version satisfies '${opts.nodeRange}'`); 44 | } 45 | 46 | const fetched = localPlace({ from: 'fetched', arch, nodeVersion, platform, version }); 47 | const built = localPlace({ from: 'built', arch, nodeVersion, platform, version }); 48 | const remote = remotePlace({ arch, nodeVersion, platform, version }); 49 | 50 | let fetchFailed; 51 | if (!forceBuild) { 52 | if (await exists(fetched)) { 53 | if (dryRun) return 'exists'; 54 | return fetched; 55 | } 56 | } 57 | if (!forceFetch) { 58 | if (await exists(built)) { 59 | if (dryRun) return 'exists'; 60 | if (forceBuild) log.info('Reusing base binaries built locally:', built); 61 | return built; 62 | } 63 | } 64 | if (!forceBuild) { 65 | if (dryRun) return 'fetched'; 66 | if (await cloud.download(remote, fetched)) return fetched; 67 | fetchFailed = true; 68 | } 69 | if (!dryRun && fetchFailed) { 70 | log.info('Not found in GitHub releases:', JSON.stringify(remote)); 71 | } 72 | if (!dryRun) { 73 | log.info('Building base binary from source:', path.basename(built)); 74 | } 75 | if (hostPlatform !== platform) { 76 | throw wasReported(`Not able to build for '${opts.platform}' here, only for '${hostPlatform}'`); 77 | } 78 | if (hostArch !== arch) { 79 | throw wasReported(`Not able to build for '${opts.arch}' here, only for '${hostArch}'`); 80 | } 81 | if (knownArchs.indexOf(arch) < 0) { 82 | throw wasReported(`Unknown arch '${opts.arch}'. Specify ${knownArchs.join(', ')}`); 83 | } 84 | 85 | if (dryRun) return 'built'; 86 | await build(nodeVersion, arch, built); 87 | return built; 88 | } 89 | 90 | export { system }; 91 | -------------------------------------------------------------------------------- /patches/backport.R24262.patch: -------------------------------------------------------------------------------- 1 | commit 667f15a1047eeadf4cbadbb50dafe6541745cdc3 2 | Author: yangguo@chromium.org 3 | Date: Mon Sep 29 07:14:05 2014 +0000 4 | 5 | Fix serializing ICs. 6 | 7 | R=mvstanton@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/587213002 10 | 11 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 12 | 13 | diff --git a/src/serialize.cc b/src/serialize.cc 14 | index 894a1be..a2dde9b 100644 15 | --- node/deps/v8/src/serialize.cc 16 | +++ node/deps/v8/src/serialize.cc 17 | @@ -1894,15 +1894,26 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, 18 | 19 | if (heap_object->IsCode()) { 20 | Code* code_object = Code::cast(heap_object); 21 | - DCHECK(!code_object->is_optimized_code()); 22 | - if (code_object->kind() == Code::BUILTIN) { 23 | - SerializeBuiltin(code_object, how_to_code, where_to_point, skip); 24 | - return; 25 | - } else if (code_object->IsCodeStubOrIC()) { 26 | - SerializeCodeStub(code_object, how_to_code, where_to_point, skip); 27 | - return; 28 | + switch (code_object->kind()) { 29 | + case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet. 30 | + case Code::HANDLER: // No handlers patched in yet. 31 | + case Code::REGEXP: // No regexp literals initialized yet. 32 | + case Code::NUMBER_OF_KINDS: // Pseudo enum value. 33 | + CHECK(false); 34 | + case Code::BUILTIN: 35 | + SerializeBuiltin(code_object, how_to_code, where_to_point, skip); 36 | + return; 37 | + case Code::STUB: 38 | + SerializeCodeStub(code_object, how_to_code, where_to_point, skip); 39 | + return; 40 | +#define IC_KIND_CASE(KIND) case Code::KIND: 41 | + IC_KIND_LIST(IC_KIND_CASE) 42 | +#undef IC_KIND_CASE 43 | + // TODO(yangguo): add special handling to canonicalize ICs. 44 | + case Code::FUNCTION: 45 | + SerializeHeapObject(code_object, how_to_code, where_to_point, skip); 46 | + return; 47 | } 48 | - code_object->ClearInlineCaches(); 49 | } 50 | 51 | if (heap_object == source_) { 52 | @@ -1967,20 +1978,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, 53 | } 54 | 55 | 56 | -void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code, 57 | +void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code, 58 | WhereToPoint where_to_point, int skip) { 59 | DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || 60 | (how_to_code == kPlain && where_to_point == kInnerPointer) || 61 | (how_to_code == kFromCode && where_to_point == kInnerPointer)); 62 | - uint32_t stub_key = code->stub_key(); 63 | - 64 | - if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) { 65 | - if (FLAG_trace_code_serializer) { 66 | - PrintF("Encoding uncacheable code stub as heap object\n"); 67 | - } 68 | - SerializeHeapObject(code, how_to_code, where_to_point, skip); 69 | - return; 70 | - } 71 | + uint32_t stub_key = stub->stub_key(); 72 | + DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); 73 | 74 | if (skip != 0) { 75 | sink_->Put(kSkip, "SkipFromSerializeCodeStub"); 76 | diff --git a/src/serialize.h b/src/serialize.h 77 | index 7831536..b6ad82c 100644 78 | --- node/deps/v8/src/serialize.h 79 | +++ node/deps/v8/src/serialize.h 80 | @@ -607,7 +607,7 @@ class CodeSerializer : public Serializer { 81 | private: 82 | void SerializeBuiltin(Code* builtin, HowToCode how_to_code, 83 | WhereToPoint where_to_point, int skip); 84 | - void SerializeCodeStub(Code* code, HowToCode how_to_code, 85 | + void SerializeCodeStub(Code* stub, HowToCode how_to_code, 86 | WhereToPoint where_to_point, int skip); 87 | void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point, 88 | int skip); 89 | -------------------------------------------------------------------------------- /lib/build.js: -------------------------------------------------------------------------------- 1 | import { mkdirp, remove } from 'fs-extra'; 2 | import { progress, spawn } from './spawn.js'; 3 | import { copyFile } from './copy-file.js'; 4 | import { hostPlatform } from './system.js'; 5 | import { log } from './log.js'; 6 | import patchesJson from '../patches/patches.json'; 7 | import path from 'path'; 8 | import { tempPath } from './temp-path.js'; 9 | import thresholds from './thresholds.js'; 10 | 11 | let buildPath; 12 | if (process.env.GITHUB_USERNAME) { 13 | buildPath = path.join(__dirname, '..', 'precompile'); 14 | } else { 15 | buildPath = tempPath(); 16 | } 17 | 18 | const nodePath = path.join(buildPath, 'node'); 19 | const patchesPath = path.resolve(__dirname, '../patches'); 20 | const nodeRepo = 'https://github.com/nodejs/node'; 21 | 22 | async function gitClone (nodeVersion) { 23 | log.info('Cloning Node.js repository from GitHub...'); 24 | const args = [ 'clone', '-b', nodeVersion, '--depth', '1', '--single-branch', '--bare', '--progress', nodeRepo, 'node/.git' ]; 25 | const promise = spawn('git', args, { cwd: buildPath }); 26 | progress(promise, thresholds('clone')); 27 | await promise; 28 | } 29 | 30 | async function gitResetHard (nodeVersion) { 31 | log.info(`Checking out ${nodeVersion}`); 32 | const patches = patchesJson[nodeVersion]; 33 | const commit = patches.commit || nodeVersion; 34 | const args = [ '--work-tree', '.', 'reset', '--hard', commit ]; 35 | await spawn('git', args, { cwd: nodePath }); 36 | } 37 | 38 | async function applyPatches (nodeVersion) { 39 | log.info('Applying patches'); 40 | let patches = patchesJson[nodeVersion]; 41 | patches = patches.patches || patches; 42 | if (patches.sameAs) patches = patchesJson[patches.sameAs]; 43 | for (const patch of patches) { 44 | const patchPath = path.join(patchesPath, patch); 45 | const args = [ '-p1', '-i', patchPath ]; 46 | await spawn('patch', args, { cwd: nodePath }); 47 | } 48 | } 49 | 50 | async function compileOnWindows (nodeVersion, targetArch) { 51 | const args = []; 52 | args.push('/c', 'vcbuild.bat', targetArch, 'noetw'); 53 | const major = nodeVersion.match(/^v?(\d+)/)[1] | 0; 54 | if (major <= 10) args.push('nosign', 'noperfctr'); 55 | const promise = spawn('cmd', args, { cwd: nodePath }); 56 | progress(promise, thresholds('vcbuild', nodeVersion)); 57 | await promise; 58 | if (major <= 10) return path.join(nodePath, 'Release/node.exe'); 59 | return path.join(nodePath, 'out/Release/node.exe'); 60 | } 61 | 62 | async function compileOnUnix (nodeVersion, targetArch) { 63 | const args = []; 64 | const cpu = { x86: 'ia32', x64: 'x64', 65 | armv6: 'arm', armv7: 'arm', arm64: 'arm64', ppc64: 'ppc64', s390x: 's390x' }[targetArch]; 66 | args.push('--dest-cpu', cpu); 67 | // first of all v8_inspector introduces the use 68 | // of `prime_rehash_policy` symbol that requires 69 | // GLIBCXX_3.4.18 on some systems 70 | // also we don't support any kind of debugging 71 | // against packaged apps, hence v8_inspector is useless 72 | const major = nodeVersion.match(/^v?(\d+)/)[1] | 0; 73 | if (major >= 6) args.push('--without-inspector'); 74 | // https://github.com/mhart/alpine-node/blob/base-7.4.0/Dockerfile#L33 75 | if (hostPlatform === 'alpine') args.push('--without-snapshot'); 76 | // TODO same for windows? 77 | await spawn('./configure', args, { cwd: nodePath }); 78 | const make = hostPlatform === 'freebsd' ? 'gmake' : 'make'; 79 | const promise = spawn(make, [], { cwd: nodePath }); 80 | progress(promise, thresholds('make', nodeVersion)); 81 | await promise; 82 | const output = path.join(nodePath, 'out/Release/node'); 83 | // https://github.com/mhart/alpine-node/blob/base-7.4.0/Dockerfile#L36 84 | if (hostPlatform === 'alpine') await spawn('paxctl', [ '-cm', output ]); 85 | return output; 86 | } 87 | 88 | async function compile (nodeVersion, targetArch) { 89 | log.info('Compiling Node.js from sources...'); 90 | const win = hostPlatform === 'win'; 91 | if (win) return await compileOnWindows(nodeVersion, targetArch); 92 | return await compileOnUnix(nodeVersion, targetArch); 93 | } 94 | 95 | export default async function build ( 96 | nodeVersion, targetArch, local 97 | ) { 98 | await remove(buildPath); 99 | await mkdirp(buildPath); 100 | await gitClone(nodeVersion); 101 | await gitResetHard(nodeVersion); 102 | await applyPatches(nodeVersion); 103 | const output = await compile(nodeVersion, targetArch); 104 | await mkdirp(path.dirname(local)); 105 | await copyFile(output, local); 106 | await remove(buildPath); 107 | } 108 | -------------------------------------------------------------------------------- /patches/backport.R25444.patch: -------------------------------------------------------------------------------- 1 | commit c64b47f55237a78b6d74baa1503e7218b94811e4 2 | Author: yangguo 3 | Date: Thu Nov 20 08:20:48 2014 -0800 4 | 5 | When optimizing deserialized code, make sure IC state is preserved. 6 | 7 | R=jkummerow@chromium.org 8 | 9 | Review URL: https://codereview.chromium.org/737373003 10 | 11 | Cr-Commit-Position: refs/heads/master@{#25444} 12 | 13 | diff --git a/src/compiler.cc b/src/compiler.cc 14 | index 3b612c1..33d88d7 100644 15 | --- node/deps/v8/src/compiler.cc 16 | +++ node/deps/v8/src/compiler.cc 17 | @@ -384,13 +384,21 @@ 18 | if (FLAG_hydrogen_stats) { 19 | timer.Start(); 20 | } 21 | - CompilationInfoWithZone unoptimized(info()->shared_info()); 22 | + Handle shared = info()->shared_info(); 23 | + CompilationInfoWithZone unoptimized(shared); 24 | // Note that we use the same AST that we will use for generating the 25 | // optimized code. 26 | unoptimized.SetFunction(info()->function()); 27 | unoptimized.PrepareForCompilation(info()->scope()); 28 | unoptimized.SetContext(info()->context()); 29 | if (should_recompile) unoptimized.EnableDeoptimizationSupport(); 30 | + // If the current code has reloc info for serialization, also include 31 | + // reloc info for serialization for the new code, so that deopt support 32 | + // can be added without losing IC state. 33 | + if (shared->code()->kind() == Code::FUNCTION && 34 | + shared->code()->has_reloc_info_for_serialization()) { 35 | + unoptimized.PrepareForSerializing(); 36 | + } 37 | bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); 38 | if (should_recompile) { 39 | if (!succeeded) return SetLastStatus(FAILED); 40 | diff --git a/src/flag-definitions.h b/src/flag-definitions.h 41 | index 535dcd2..0d7363e 100644 42 | --- node/deps/v8/src/flag-definitions.h 43 | +++ node/deps/v8/src/flag-definitions.h 44 | @@ -427,7 +427,8 @@ 45 | DEFINE_BOOL(trace_stub_failures, false, 46 | "trace deoptimization of generated code stubs") 47 | 48 | -DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts") 49 | +DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts") 50 | +DEFINE_BOOL(serialize_inner, true, "enable caching of inner functions") 51 | DEFINE_BOOL(trace_code_serializer, false, "trace code serializer") 52 | 53 | // compiler.cc 54 | diff --git a/src/full-codegen.cc b/src/full-codegen.cc 55 | index e32c59f..cb8f4aa 100644 56 | --- node/deps/v8/src/full-codegen.cc 57 | +++ node/deps/v8/src/full-codegen.cc 58 | @@ -321,6 +321,7 @@ 59 | cgen.PopulateDeoptimizationData(code); 60 | cgen.PopulateTypeFeedbackInfo(code); 61 | code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); 62 | + code->set_has_reloc_info_for_serialization(info->will_serialize()); 63 | code->set_handler_table(*cgen.handler_table()); 64 | code->set_compiled_optimizable(info->IsOptimizable()); 65 | code->set_allow_osr_at_loop_nesting_level(0); 66 | diff --git a/src/objects-inl.h b/src/objects-inl.h 67 | index 3dd6fed..108f9f6 100644 68 | --- node/deps/v8/src/objects-inl.h 69 | +++ node/deps/v8/src/objects-inl.h 70 | @@ -4794,6 +4794,21 @@ 71 | } 72 | 73 | 74 | +bool Code::has_reloc_info_for_serialization() { 75 | + DCHECK_EQ(FUNCTION, kind()); 76 | + byte flags = READ_BYTE_FIELD(this, kFullCodeFlags); 77 | + return FullCodeFlagsHasRelocInfoForSerialization::decode(flags); 78 | +} 79 | + 80 | + 81 | +void Code::set_has_reloc_info_for_serialization(bool value) { 82 | + DCHECK_EQ(FUNCTION, kind()); 83 | + byte flags = READ_BYTE_FIELD(this, kFullCodeFlags); 84 | + flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value); 85 | + WRITE_BYTE_FIELD(this, kFullCodeFlags, flags); 86 | +} 87 | + 88 | + 89 | int Code::allow_osr_at_loop_nesting_level() { 90 | DCHECK_EQ(FUNCTION, kind()); 91 | int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 92 | diff --git a/src/objects.h b/src/objects.h 93 | index 678dcb2..9569de9 100644 94 | --- node/deps/v8/src/objects.h 95 | +++ node/deps/v8/src/objects.h 96 | @@ -5597,6 +5597,12 @@ 97 | inline bool is_compiled_optimizable(); 98 | inline void set_compiled_optimizable(bool value); 99 | 100 | + // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its 101 | + // reloc info includes runtime and external references to support 102 | + // serialization/deserialization. 103 | + inline bool has_reloc_info_for_serialization(); 104 | + inline void set_has_reloc_info_for_serialization(bool value); 105 | + 106 | // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for 107 | // how long the function has been marked for OSR and therefore which 108 | // level of loop nesting we are willing to do on-stack replacement 109 | @@ -5873,6 +5879,8 @@ 110 | public BitField {}; // NOLINT 111 | class FullCodeFlagsHasDebugBreakSlotsField: public BitField {}; 112 | class FullCodeFlagsIsCompiledOptimizable: public BitField {}; 113 | + class FullCodeFlagsHasRelocInfoForSerialization 114 | + : public BitField {}; 115 | 116 | static const int kProfilerTicksOffset = kFullCodeFlags + 1; 117 | 118 | -------------------------------------------------------------------------------- /patches/backport.PR4777.for.N0.patch: -------------------------------------------------------------------------------- 1 | From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001 2 | From: Fedor Indutny 3 | Date: Wed, 20 Jan 2016 19:34:19 -0500 4 | Subject: vm: introduce `cachedData`/`produceCachedData` 5 | 6 | Introduce `cachedData`/`produceCachedData` options for `v8.Script`. 7 | Could be used to consume/produce V8's code cache for speeding up 8 | compilation of known code. 9 | 10 | PR-URL: https://github.com/nodejs/node/pull/4777 11 | Reviewed-By: Ben Noordhuis 12 | 13 | diff --git a/src/node_contextify.cc b/src/node_contextify.cc 14 | index 2e8fd2c..1b3d618 100644 15 | --- a/src/node_contextify.cc 16 | +++ b/src/node_contextify.cc 17 | @@ -18,10 +18,11 @@ 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #include "node.h" 23 | +#include "node_buffer.h" 24 | #include "node_internals.h" 25 | #include "node_watchdog.h" 26 | #include "base-object.h" 27 | #include "base-object-inl.h" 28 | #include "env.h" 29 | @@ -484,28 +485,60 @@ class ContextifyScript : public BaseObject { 30 | 31 | TryCatch try_catch; 32 | Local code = args[0]->ToString(); 33 | Local filename = GetFilenameArg(args, 1); 34 | bool display_errors = GetDisplayErrorsArg(args, 1); 35 | + Local cached_data_buf = GetCachedData(args, 1); 36 | + bool produce_cached_data = GetProduceCachedData(args, 1); 37 | if (try_catch.HasCaught()) { 38 | try_catch.ReThrow(); 39 | return; 40 | } 41 | 42 | + ScriptCompiler::CachedData* cached_data = NULL; 43 | + if (!cached_data_buf.IsEmpty()) { 44 | + cached_data = new ScriptCompiler::CachedData( 45 | + reinterpret_cast(Buffer::Data(cached_data_buf)), 46 | + Buffer::Length(cached_data_buf)); 47 | + } 48 | + 49 | ScriptOrigin origin(filename); 50 | - ScriptCompiler::Source source(code, origin); 51 | - Local v8_script = 52 | - ScriptCompiler::CompileUnbound(env->isolate(), &source); 53 | + ScriptCompiler::Source source(code, origin, cached_data); 54 | + ScriptCompiler::CompileOptions compile_options = 55 | + ScriptCompiler::kNoCompileOptions; 56 | + 57 | + if (source.GetCachedData() != NULL) 58 | + compile_options = ScriptCompiler::kConsumeCodeCache; 59 | + else if (produce_cached_data) 60 | + compile_options = ScriptCompiler::kProduceCodeCache; 61 | + 62 | + Local v8_script = ScriptCompiler::CompileUnbound( 63 | + env->isolate(), 64 | + &source, 65 | + compile_options); 66 | 67 | if (v8_script.IsEmpty()) { 68 | if (display_errors) { 69 | AppendExceptionLine(env, try_catch.Exception(), try_catch.Message()); 70 | } 71 | try_catch.ReThrow(); 72 | return; 73 | } 74 | contextify_script->script_.Reset(env->isolate(), v8_script); 75 | + 76 | + if (compile_options == ScriptCompiler::kConsumeCodeCache) { 77 | + // no 'rejected' field in cachedData 78 | + } else if (compile_options == ScriptCompiler::kProduceCodeCache) { 79 | + const ScriptCompiler::CachedData* cached_data = source.GetCachedData(); 80 | + Local buf = Buffer::New( 81 | + env, 82 | + reinterpret_cast(cached_data->data), 83 | + cached_data->length); 84 | + Local cached_data_string = FIXED_ONE_BYTE_STRING( 85 | + args.GetIsolate(), "cachedData"); 86 | + args.This()->Set(cached_data_string, buf); 87 | + } 88 | } 89 | 90 | 91 | static bool InstanceOf(Environment* env, const Local& value) { 92 | return !value.IsEmpty() && 93 | @@ -656,10 +689,46 @@ class ContextifyScript : public BaseObject { 94 | 95 | return value->IsUndefined() ? defaultFilename : value->ToString(); 96 | } 97 | 98 | 99 | + static Local GetCachedData( 100 | + const FunctionCallbackInfo& args, 101 | + const int i) { 102 | + if (!args[i]->IsObject()) { 103 | + return Local(); 104 | + } 105 | + Local key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "cachedData"); 106 | + Local value = args[i].As()->Get(key); 107 | + if (value->IsUndefined()) { 108 | + return Local(); 109 | + } 110 | + 111 | + if (!Buffer::HasInstance(value)) { 112 | + Environment::ThrowTypeError( 113 | + args.GetIsolate(), 114 | + "options.cachedData must be a Buffer instance"); 115 | + return Local(); 116 | + } 117 | + 118 | + return value; 119 | + } 120 | + 121 | + 122 | + static bool GetProduceCachedData( 123 | + const FunctionCallbackInfo& args, 124 | + const int i) { 125 | + if (!args[i]->IsObject()) { 126 | + return false; 127 | + } 128 | + Local key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "produceCachedData"); 129 | + Local value = args[i].As()->Get(key); 130 | + 131 | + return value->IsTrue(); 132 | + } 133 | + 134 | + 135 | static bool EvalMachine(Environment* env, 136 | const int64_t timeout, 137 | const bool display_errors, 138 | const FunctionCallbackInfo& args, 139 | TryCatch& try_catch) { 140 | -------------------------------------------------------------------------------- /lib/github.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | 3 | import { log, wasReported } from './log.js'; 4 | import assert from 'assert'; 5 | import fs from 'fs'; 6 | import progress from 'request-progress'; 7 | import request from 'request'; 8 | 9 | export class GitHub { 10 | constructor ({ owner, repo }) { 11 | this.owner = owner; 12 | this.repo = repo; 13 | const { GITHUB_USERNAME, GITHUB_PASSWORD } = process.env; 14 | const auth = { user: GITHUB_USERNAME, pass: GITHUB_PASSWORD }; 15 | this.request = request.defaults({ 16 | auth: auth.user ? auth : undefined, 17 | headers: { 'User-Agent': `${this.owner}/${this.repo}/${GITHUB_USERNAME}` }, 18 | timeout: 30 * 1000 19 | }); 20 | } 21 | 22 | getRelease (tag) { 23 | return new Promise((resolve, reject) => { 24 | const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases/tags/${tag}`; 25 | this.request(url, (error, response, body) => { 26 | if (error) return reject(wasReported(error.message)); 27 | const release = JSON.parse(body); 28 | const { message } = release; 29 | if (message === 'Not Found') return resolve(undefined); 30 | if (message) return reject(wasReported(message)); 31 | resolve(release); 32 | }); 33 | }); 34 | } 35 | 36 | getReleaseDraft (tag) { 37 | return new Promise((resolve, reject) => { 38 | const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases`; 39 | this.request(url, (error, response, body) => { 40 | if (error) return reject(wasReported(error.message)); 41 | // here we use `get release by tag` endpoint 42 | // because draft releases are really `untagged`. 43 | // seems that `get release by tag` is for non-drafts. 44 | // hence listing all releases and looking through them 45 | const releases = JSON.parse(body); 46 | if (releases.message) return reject(wasReported(releases.message)); 47 | const found = releases.filter(({ tag_name }) => tag_name === tag); // eslint-disable-line camelcase 48 | assert(found.length <= 1); 49 | if (!found.length) return resolve(undefined); 50 | resolve(found[0]); 51 | }); 52 | }); 53 | } 54 | 55 | createRelease (tag) { 56 | return new Promise((resolve, reject) => { 57 | const form = JSON.stringify({ 58 | tag_name: tag, 59 | target_commitish: 'master', // TODO maybe git rev-parse HEAD 60 | name: tag, 61 | draft: true, 62 | prerelease: true 63 | }); 64 | const url = `https://api.github.com/repos/${this.owner}/${this.repo}/releases`; 65 | this.request.post(url, { form }, (error, response, body) => { 66 | if (error) return reject(wasReported(error.message)); 67 | const release = JSON.parse(body); 68 | if (release.message) return reject(wasReported(release.message)); 69 | resolve(release); 70 | }); 71 | }); 72 | } 73 | 74 | uploadAsset (file, release, name) { 75 | assert(!(/[\\/]/.test(name))); 76 | return new Promise((resolve, reject) => { 77 | fs.stat(file, (error, stat) => { 78 | if (error) return reject(error); 79 | const headers = { 80 | 'Content-Length': stat.size, 81 | 'Content-Type': 'application/octet-stream' 82 | }; 83 | const rs = fs.createReadStream(file); 84 | const subst = `?name=${name}`; 85 | const url = release.upload_url.replace(/\{\?name,label\}/, subst); 86 | const req = this.request.post(url, { 87 | headers, timeout: 30 * 60 * 1000 88 | }, (error2, response, body) => { 89 | if (error2) return reject(wasReported(error2.message)); 90 | const asset = JSON.parse(body); 91 | const { errors } = asset; 92 | if (errors && errors[0]) return reject(wasReported(errors[0].code)); 93 | if (asset.message) return reject(wasReported(asset.message)); 94 | resolve(asset); 95 | }); 96 | rs.pipe(req); 97 | }); 98 | }); 99 | } 100 | 101 | downloadUrl (url, file, short) { 102 | log.enableProgress(short); 103 | log.showProgress(0); 104 | return new Promise((resolve, reject) => { 105 | const headers = { Accept: 'application/octet-stream' }; 106 | const ws = fs.createWriteStream(file); 107 | let result; 108 | const req = progress(this.request.get(url, { 109 | headers 110 | }, (error, response) => { 111 | if (error) { 112 | log.disableProgress(); 113 | return reject(wasReported(error.message)); 114 | } 115 | if (response.statusCode !== 200) { 116 | log.disableProgress(); 117 | const message = `${response.statusCode} ${response.body}`; 118 | return reject(wasReported(message, url)); 119 | } 120 | result = response; 121 | })); 122 | req.on('progress', (state) => { 123 | let p; 124 | if (state.size && state.size.transferred && state.size.total) { 125 | p = state.size.transferred / state.size.total; 126 | } else { 127 | p = state.percentage; 128 | } 129 | log.showProgress(p * 100); 130 | }); 131 | req.pipe(ws); 132 | ws.on('close', () => { 133 | log.showProgress(100); 134 | log.disableProgress(); 135 | resolve(result); 136 | }).on('error', (error) => { 137 | log.disableProgress(); 138 | reject(wasReported(error.message)); 139 | }); 140 | }); 141 | } 142 | 143 | async tryDirectly (tag, name, file, short) { 144 | try { 145 | const url = `https://github.com/${this.owner}/${this.repo}/releases/download/${tag}/${name}`; 146 | await this.downloadUrl(url, file, short); 147 | return true; 148 | } catch (error) { 149 | log.info('Asset not found by direct link:', JSON.stringify({ tag, name })); 150 | return false; 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /patches/backport.PR4777.for.N4.patch: -------------------------------------------------------------------------------- 1 | From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001 2 | From: Fedor Indutny 3 | Date: Wed, 20 Jan 2016 19:34:19 -0500 4 | Subject: vm: introduce `cachedData`/`produceCachedData` 5 | 6 | Introduce `cachedData`/`produceCachedData` options for `v8.Script`. 7 | Could be used to consume/produce V8's code cache for speeding up 8 | compilation of known code. 9 | 10 | PR-URL: https://github.com/nodejs/node/pull/4777 11 | Reviewed-By: Ben Noordhuis 12 | 13 | diff --git a/src/env.h b/src/env.h 14 | index 7b6ffc8..5c99f80 100644 15 | --- a/src/env.h 16 | +++ b/src/env.h 17 | @@ -53,10 +53,12 @@ namespace node { 18 | V(blocks_string, "blocks") \ 19 | V(buffer_string, "buffer") \ 20 | V(bytes_string, "bytes") \ 21 | V(bytes_parsed_string, "bytesParsed") \ 22 | V(bytes_read_string, "bytesRead") \ 23 | + V(cached_data_string, "cachedData") \ 24 | + V(cached_data_rejected_string, "cachedDataRejected") \ 25 | V(callback_string, "callback") \ 26 | V(change_string, "change") \ 27 | V(oncertcb_string, "oncertcb") \ 28 | V(onclose_string, "_onclose") \ 29 | V(code_string, "code") \ 30 | @@ -165,10 +167,11 @@ namespace node { 31 | V(pipe_string, "pipe") \ 32 | V(port_string, "port") \ 33 | V(preference_string, "preference") \ 34 | V(priority_string, "priority") \ 35 | V(processed_string, "processed") \ 36 | + V(produce_cached_data_string, "produceCachedData") \ 37 | V(prototype_string, "prototype") \ 38 | V(raw_string, "raw") \ 39 | V(rdev_string, "rdev") \ 40 | V(readable_string, "readable") \ 41 | V(received_shutdown_string, "receivedShutdown") \ 42 | diff --git a/src/node_contextify.cc b/src/node_contextify.cc 43 | index 7404bbb..ecf9444 100644 44 | --- a/src/node_contextify.cc 45 | +++ b/src/node_contextify.cc 46 | @@ -1,6 +1,7 @@ 47 | #include "node.h" 48 | +#include "node_buffer.h" 49 | #include "node_internals.h" 50 | #include "node_watchdog.h" 51 | #include "base-object.h" 52 | #include "base-object-inl.h" 53 | #include "env.h" 54 | @@ -11,10 +12,11 @@ 55 | 56 | namespace node { 57 | 58 | using v8::AccessType; 59 | using v8::Array; 60 | +using v8::ArrayBuffer; 61 | using v8::Boolean; 62 | using v8::Context; 63 | using v8::Debug; 64 | using v8::EscapableHandleScope; 65 | using v8::External; 66 | @@ -474,28 +476,61 @@ class ContextifyScript : public BaseObject { 67 | Local code = args[0]->ToString(env->isolate()); 68 | Local filename = GetFilenameArg(args, 1); 69 | Local lineOffset = GetLineOffsetArg(args, 1); 70 | Local columnOffset = GetColumnOffsetArg(args, 1); 71 | bool display_errors = GetDisplayErrorsArg(args, 1); 72 | + MaybeLocal cached_data_buf = GetCachedData(env, args, 1); 73 | + bool produce_cached_data = GetProduceCachedData(env, args, 1); 74 | if (try_catch.HasCaught()) { 75 | try_catch.ReThrow(); 76 | return; 77 | } 78 | 79 | + ScriptCompiler::CachedData* cached_data = nullptr; 80 | + if (!cached_data_buf.IsEmpty()) { 81 | + auto cached_data_local = cached_data_buf.ToLocalChecked(); 82 | + cached_data = new ScriptCompiler::CachedData( 83 | + reinterpret_cast(Buffer::Data(cached_data_local)), 84 | + Buffer::Length(cached_data_local)); 85 | + } 86 | + 87 | ScriptOrigin origin(filename, lineOffset, columnOffset); 88 | - ScriptCompiler::Source source(code, origin); 89 | - Local v8_script = 90 | - ScriptCompiler::CompileUnbound(env->isolate(), &source); 91 | + ScriptCompiler::Source source(code, origin, cached_data); 92 | + ScriptCompiler::CompileOptions compile_options = 93 | + ScriptCompiler::kNoCompileOptions; 94 | + 95 | + if (source.GetCachedData() != nullptr) 96 | + compile_options = ScriptCompiler::kConsumeCodeCache; 97 | + else if (produce_cached_data) 98 | + compile_options = ScriptCompiler::kProduceCodeCache; 99 | + 100 | + Local v8_script = ScriptCompiler::CompileUnbound( 101 | + env->isolate(), 102 | + &source, 103 | + compile_options); 104 | 105 | if (v8_script.IsEmpty()) { 106 | if (display_errors) { 107 | AppendExceptionLine(env, try_catch.Exception(), try_catch.Message()); 108 | } 109 | try_catch.ReThrow(); 110 | return; 111 | } 112 | contextify_script->script_.Reset(env->isolate(), v8_script); 113 | + 114 | + if (compile_options == ScriptCompiler::kConsumeCodeCache) { 115 | + args.This()->Set( 116 | + env->cached_data_rejected_string(), 117 | + Boolean::New(env->isolate(), source.GetCachedData()->rejected)); 118 | + } else if (compile_options == ScriptCompiler::kProduceCodeCache) { 119 | + const ScriptCompiler::CachedData* cached_data = source.GetCachedData(); 120 | + MaybeLocal buf = Buffer::Copy( 121 | + env, 122 | + reinterpret_cast(cached_data->data), 123 | + cached_data->length); 124 | + args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); 125 | + } 126 | } 127 | 128 | 129 | static bool InstanceOf(Environment* env, const Local& value) { 130 | return !value.IsEmpty() && 131 | @@ -644,10 +679,47 @@ class ContextifyScript : public BaseObject { 132 | return defaultFilename; 133 | return value->ToString(args.GetIsolate()); 134 | } 135 | 136 | 137 | + static MaybeLocal GetCachedData( 138 | + Environment* env, 139 | + const FunctionCallbackInfo& args, 140 | + const int i) { 141 | + if (!args[i]->IsObject()) { 142 | + return MaybeLocal(); 143 | + } 144 | + Local value = args[i].As()->Get(env->cached_data_string()); 145 | + if (value->IsUndefined()) { 146 | + return MaybeLocal(); 147 | + } 148 | + 149 | + if (!Buffer::HasInstance(value)) { 150 | + Environment::ThrowTypeError( 151 | + args.GetIsolate(), 152 | + "options.cachedData must be a Buffer instance"); 153 | + return MaybeLocal(); 154 | + } 155 | + 156 | + return value; 157 | + } 158 | + 159 | + 160 | + static bool GetProduceCachedData( 161 | + Environment* env, 162 | + const FunctionCallbackInfo& args, 163 | + const int i) { 164 | + if (!args[i]->IsObject()) { 165 | + return false; 166 | + } 167 | + Local value = 168 | + args[i].As()->Get(env->produce_cached_data_string()); 169 | + 170 | + return value->IsTrue(); 171 | + } 172 | + 173 | + 174 | static Local GetLineOffsetArg( 175 | const FunctionCallbackInfo& args, 176 | const int i) { 177 | Local defaultLineOffset = Integer::New(args.GetIsolate(), 0); 178 | 179 | -------------------------------------------------------------------------------- /patches/backport.R24824.patch: -------------------------------------------------------------------------------- 1 | commit 7753ace1354ac231374da0446a5057b6b40780db 2 | Author: yangguo@chromium.org 3 | Date: Thu Oct 23 08:25:42 2014 +0000 4 | 5 | Small fixes for the code serializer. 6 | - assertions regarding max heap object size. 7 | - ensure string table capacity upfront. 8 | 9 | R=mvstanton@chromium.org 10 | 11 | Review URL: https://codereview.chromium.org/671843003 12 | 13 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24824 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 14 | 15 | diff --git a/src/objects.cc b/src/objects.cc 16 | index 2685a5c..371931c 100644 17 | --- node/deps/v8/src/objects.cc 18 | +++ node/deps/v8/src/objects.cc 19 | @@ -14769,6 +14769,16 @@ MaybeHandle StringTable::LookupTwoCharsStringIfExists( 20 | } 21 | 22 | 23 | +void StringTable::EnsureCapacityForDeserialization(Isolate* isolate, 24 | + int expected) { 25 | + Handle table = isolate->factory()->string_table(); 26 | + // We need a key instance for the virtual hash function. 27 | + InternalizedStringKey dummy_key(Handle::null()); 28 | + table = StringTable::EnsureCapacity(table, expected, &dummy_key); 29 | + isolate->factory()->set_string_table(table); 30 | +} 31 | + 32 | + 33 | Handle StringTable::LookupString(Isolate* isolate, 34 | Handle string) { 35 | InternalizedStringKey key(string); 36 | diff --git a/src/objects.h b/src/objects.h 37 | index 7e509e7..b2b64c2 100644 38 | --- node/deps/v8/src/objects.h 39 | +++ node/deps/v8/src/objects.h 40 | @@ -3446,6 +3446,8 @@ class StringTable: public HashTable= 0 && space < kNumberOfPreallocatedSpaces); 57 | - DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize); 58 | + DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize); 59 | uint32_t new_chunk_size = pending_chunk_[space] + size; 60 | uint32_t allocation; 61 | if (new_chunk_size > static_cast(Page::kMaxRegularHeapObjectSize)) { 62 | @@ -2081,6 +2084,8 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, 63 | PrintF("\n"); 64 | } 65 | 66 | + if (heap_object->IsInternalizedString()) num_internalized_strings_++; 67 | + 68 | // Object has not yet been serialized. Serialize it here. 69 | ObjectSerializer serializer(this, heap_object, sink_, how_to_code, 70 | where_to_point); 71 | @@ -2201,6 +2206,11 @@ MaybeHandle CodeSerializer::Deserialize( 72 | SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); 73 | Deserializer deserializer(&payload); 74 | 75 | + // Eagerly expand string table to avoid allocations during deserialization. 76 | + StringTable::EnsureCapacityForDeserialization(isolate, 77 | + scd.NumInternalizedStrings()); 78 | + 79 | + // Set reservations. 80 | STATIC_ASSERT(NEW_SPACE == 0); 81 | int current_space = NEW_SPACE; 82 | Vector res = scd.Reservations(); 83 | @@ -2254,7 +2264,7 @@ SerializedCodeData::SerializedCodeData(List* payload, CodeSerializer* cs) 84 | Vector chunks = cs->FinalAllocationChunks(i); 85 | for (int j = 0; j < chunks.length(); j++) { 86 | DCHECK(i == LO_SPACE || 87 | - chunks[j] < 88 | + chunks[j] <= 89 | static_cast(Page::kMaxRegularHeapObjectSize)); 90 | uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | 91 | IsLastChunkBits::encode(j == chunks.length() - 1); 92 | @@ -2277,6 +2287,7 @@ SerializedCodeData::SerializedCodeData(List* payload, CodeSerializer* cs) 93 | 94 | // Set header values. 95 | SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); 96 | + SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings()); 97 | SetHeaderValue(kReservationsOffset, reservations.length()); 98 | SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); 99 | SetHeaderValue(kPayloadLengthOffset, payload->length()); 100 | diff --git a/src/serialize.h b/src/serialize.h 101 | index 47a244f..df6723c 100644 102 | --- node/deps/v8/src/serialize.h 103 | +++ node/deps/v8/src/serialize.h 104 | @@ -264,7 +264,7 @@ class Deserializer: public SerializerDeserializer { 105 | DCHECK(space >= 0); 106 | DCHECK(space < kNumberOfSpaces); 107 | DCHECK(space == LO_SPACE || 108 | - chunk < static_cast(Page::kMaxRegularHeapObjectSize)); 109 | + chunk <= static_cast(Page::kMaxRegularHeapObjectSize)); 110 | Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c); 111 | } 112 | 113 | @@ -619,17 +619,21 @@ class CodeSerializer : public Serializer { 114 | static const int kSourceObjectIndex = 0; 115 | static const int kCodeStubsBaseIndex = 1; 116 | 117 | - String* source() { 118 | + String* source() const { 119 | DCHECK(!AllowHeapAllocation::IsAllowed()); 120 | return source_; 121 | } 122 | 123 | List* stub_keys() { return &stub_keys_; } 124 | + int num_internalized_strings() const { return num_internalized_strings_; } 125 | 126 | private: 127 | CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source, 128 | Code* main_code) 129 | - : Serializer(isolate, sink), source_(source), main_code_(main_code) { 130 | + : Serializer(isolate, sink), 131 | + source_(source), 132 | + main_code_(main_code), 133 | + num_internalized_strings_(0) { 134 | set_root_index_wave_front(Heap::kStrongRootListLength); 135 | InitializeCodeAddressMap(); 136 | } 137 | @@ -652,6 +656,7 @@ class CodeSerializer : public Serializer { 138 | DisallowHeapAllocation no_gc_; 139 | String* source_; 140 | Code* main_code_; 141 | + int num_internalized_strings_; 142 | List stub_keys_; 143 | DISALLOW_COPY_AND_ASSIGN(CodeSerializer); 144 | }; 145 | @@ -694,6 +699,10 @@ class SerializedCodeData { 146 | DISALLOW_COPY_AND_ASSIGN(Reservation); 147 | }; 148 | 149 | + int NumInternalizedStrings() const { 150 | + return GetHeaderValue(kNumInternalizedStringsOffset); 151 | + } 152 | + 153 | Vector Reservations() const { 154 | return Vector(reinterpret_cast( 155 | script_data_->data() + kHeaderSize), 156 | @@ -737,13 +746,15 @@ class SerializedCodeData { 157 | 158 | // The data header consists of int-sized entries: 159 | // [0] version hash 160 | - // [1] number of code stub keys 161 | - // [2] payload length 162 | - // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE. 163 | + // [1] number of internalized strings 164 | + // [2] number of code stub keys 165 | + // [3] payload length 166 | + // [4..10] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE. 167 | static const int kCheckSumOffset = 0; 168 | - static const int kReservationsOffset = 1; 169 | - static const int kNumCodeStubKeysOffset = 2; 170 | - static const int kPayloadLengthOffset = 3; 171 | + static const int kNumInternalizedStringsOffset = 1; 172 | + static const int kReservationsOffset = 2; 173 | + static const int kNumCodeStubKeysOffset = 3; 174 | + static const int kPayloadLengthOffset = 4; 175 | static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; 176 | 177 | class ChunkSizeBits : public BitField {}; 178 | -------------------------------------------------------------------------------- /test/upload.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | 3 | import LogMock from './log-mock.js'; 4 | import assert from 'assert'; 5 | import fs from 'fs'; 6 | import path from 'path'; 7 | import test from 'ava'; 8 | 9 | process.env.GITHUB_USERNAME = 'suppress upload error'; 10 | 11 | function relative (p) { 12 | const p2 = path.relative(__dirname, p); 13 | return p2.replace(/\\/g, '/'); 14 | } 15 | 16 | const actions = []; 17 | let lastLocal; 18 | const assets = []; 19 | 20 | require('../package.json').version = '1337.2.3'; 21 | 22 | const patchesJson = require('../patches/patches.json'); 23 | const newPatchesJson = require('./patches.json'); 24 | 25 | for (const nodeVersion in patchesJson) { 26 | delete patchesJson[nodeVersion]; 27 | } 28 | 29 | for (const nodeVersion in newPatchesJson) { 30 | patchesJson[nodeVersion] = newPatchesJson[nodeVersion]; 31 | } 32 | 33 | require('../lib/log.js').log = new LogMock(actions); 34 | 35 | require('../lib/spawn.js').spawn = function (cmd, args, opts) { 36 | assert(opts); 37 | assert(opts.cwd); 38 | if (cmd === 'git' && args[0] === 'clone') { 39 | fs.mkdirSync(path.join(opts.cwd, 'node')); 40 | } 41 | if (cmd === 'make') { 42 | fs.mkdirSync(path.join(opts.cwd, 'out')); 43 | fs.mkdirSync(path.join(opts.cwd, 'out', 'Release')); 44 | fs.writeFileSync(path.join(opts.cwd, 'out', 'Release', 'node'), 'ELF'); 45 | } 46 | if (cmd === 'cmd') { 47 | fs.mkdirSync(path.join(opts.cwd, 'Release')); 48 | fs.writeFileSync(path.join(opts.cwd, 'Release', 'node.exe'), 'MZ'); 49 | } 50 | if (cmd === 'patch') { 51 | args[args.length - 1] = relative(args[args.length - 1]); 52 | } 53 | if (opts.cwd) { 54 | opts.cwd = relative(opts.cwd); 55 | } 56 | actions.push([ cmd, args.join(' '), JSON.stringify(opts) ].join(' ')); 57 | }; 58 | 59 | require('../lib/spawn.js').progress = function () { 60 | }; 61 | 62 | require('../lib/verify.js').verify = function () { 63 | actions.push('verify'); 64 | }; 65 | 66 | require('../lib/copy-file.js').copyFile = function (src, dest) { 67 | src = relative(src); 68 | const shortDest = path.basename(path.dirname(dest)) + '/' + path.basename(dest); 69 | actions.push([ 'copyFile', src, shortDest ].join(' ')); // full dest is flaky 70 | lastLocal = dest; 71 | }; 72 | 73 | require('../lib/github.js').GitHub = class { 74 | getRelease (tag) { 75 | actions.push([ 'getRelease', tag ].join(' ')); 76 | return undefined; 77 | } 78 | 79 | getReleaseDraft (tag) { 80 | actions.push([ 'getReleaseDraft', tag ].join(' ')); 81 | return undefined; 82 | } 83 | 84 | createRelease (tag) { 85 | actions.push([ 'createRelease', tag ].join(' ')); 86 | return { upload_url: 'https://example.com/assets{?name,label}', assets }; 87 | } 88 | 89 | uploadAsset (local, release, name) { 90 | assert(local === lastLocal); // test it here. too flaky to push to actions 91 | actions.push([ 'uploadAsset', JSON.stringify(release), name ].join(' ')); 92 | assets.push({ name }); 93 | } 94 | }; 95 | 96 | test('upload', async (t) => { 97 | if (process.platform !== 'darwin' || 98 | process.arch !== 'x64') { 99 | throw new Error('RUN THE TEST ONLY ON MACOS-X64'); 100 | } 101 | 102 | const { main } = require('../lib/upload.js'); 103 | await main(); 104 | const mustBe = [ 105 | 'getRelease v1337.2', 106 | 'getReleaseDraft v1337.2', 107 | 'createRelease v1337.2', 108 | '> Building built-v0.12.15-macos-x64...', 109 | '> Cloning Node.js repository from GitHub...', 110 | 'git clone -b v0.12.15 --depth 1 --single-branch --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../precompile"}', 111 | '> Checking out v0.12.15', 112 | 'git --work-tree . reset --hard v0.12.15 {"cwd":"../precompile/node"}', 113 | '> Applying patches', 114 | 'patch -p1 -i ../patches/backport.R00000.patch {"cwd":"../precompile/node"}', 115 | 'patch -p1 -i ../patches/backport.R24002.patch {"cwd":"../precompile/node"}', 116 | 'patch -p1 -i ../patches/backport.R24204.patch {"cwd":"../precompile/node"}', 117 | 'patch -p1 -i ../patches/backport.R24262.patch {"cwd":"../precompile/node"}', 118 | 'patch -p1 -i ../patches/backport.R24266.patch {"cwd":"../precompile/node"}', 119 | 'patch -p1 -i ../patches/backport.R24523.patch {"cwd":"../precompile/node"}', 120 | 'patch -p1 -i ../patches/backport.R24543.patch {"cwd":"../precompile/node"}', 121 | 'patch -p1 -i ../patches/backport.R24639.patch {"cwd":"../precompile/node"}', 122 | 'patch -p1 -i ../patches/backport.R24642.patch {"cwd":"../precompile/node"}', 123 | 'patch -p1 -i ../patches/backport.R24643.patch {"cwd":"../precompile/node"}', 124 | 'patch -p1 -i ../patches/backport.R24644.patch {"cwd":"../precompile/node"}', 125 | 'patch -p1 -i ../patches/backport.R24824.patch {"cwd":"../precompile/node"}', 126 | 'patch -p1 -i ../patches/backport.R25039.patch {"cwd":"../precompile/node"}', 127 | 'patch -p1 -i ../patches/backport.R25444.patch {"cwd":"../precompile/node"}', 128 | 'patch -p1 -i ../patches/node.v0.12.15.patch {"cwd":"../precompile/node"}', 129 | '> Compiling Node.js from sources...', 130 | './configure --dest-cpu x64 {"cwd":"../precompile/node"}', 131 | 'make {"cwd":"../precompile/node"}', 132 | 'copyFile ../precompile/node/out/Release/node v1337.2/built-v0.12.15-macos-x64', 133 | '> Verifying built-v0.12.15-macos-x64...', 134 | 'verify', 135 | '> Uploading built-v0.12.15-macos-x64...', 136 | 'getRelease v1337.2', 137 | 'getReleaseDraft v1337.2', 138 | 'createRelease v1337.2', 139 | 'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[]} uploaded-v1337.2-node-v0.12.15-macos-x64', 140 | 'getRelease v1337.2', 141 | 'getReleaseDraft v1337.2', 142 | 'createRelease v1337.2', 143 | '> Building built-v4.4.7-macos-x64...', 144 | '> Cloning Node.js repository from GitHub...', 145 | 'git clone -b v4.4.7 --depth 1 --single-branch --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../precompile"}', 146 | '> Checking out v4.4.7', 147 | 'git --work-tree . reset --hard v4.4.7 {"cwd":"../precompile/node"}', 148 | '> Applying patches', 149 | 'patch -p1 -i ../patches/backport.R32768.v8=4.5.patch {"cwd":"../precompile/node"}', 150 | 'patch -p1 -i ../patches/node.v4.4.7.patch {"cwd":"../precompile/node"}', 151 | '> Compiling Node.js from sources...', 152 | './configure --dest-cpu x64 {"cwd":"../precompile/node"}', 153 | 'make {"cwd":"../precompile/node"}', 154 | 'copyFile ../precompile/node/out/Release/node v1337.2/built-v4.4.7-macos-x64', 155 | '> Verifying built-v4.4.7-macos-x64...', 156 | 'verify', 157 | '> Uploading built-v4.4.7-macos-x64...', 158 | 'getRelease v1337.2', 159 | 'getReleaseDraft v1337.2', 160 | 'createRelease v1337.2', 161 | 'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-macos-x64"}]} uploaded-v1337.2-node-v4.4.7-macos-x64', 162 | 'getRelease v1337.2', 163 | 'getReleaseDraft v1337.2', 164 | 'createRelease v1337.2', 165 | '> Building built-v6.3.1-macos-x64...', 166 | '> Cloning Node.js repository from GitHub...', 167 | 'git clone -b v6.3.1 --depth 1 --single-branch --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../precompile"}', 168 | '> Checking out v6.3.1', 169 | 'git --work-tree . reset --hard v6.3.1 {"cwd":"../precompile/node"}', 170 | '> Applying patches', 171 | 'patch -p1 -i ../patches/node.v6.3.1.patch {"cwd":"../precompile/node"}', 172 | '> Compiling Node.js from sources...', 173 | './configure --dest-cpu x64 --without-inspector {"cwd":"../precompile/node"}', 174 | 'make {"cwd":"../precompile/node"}', 175 | 'copyFile ../precompile/node/out/Release/node v1337.2/built-v6.3.1-macos-x64', 176 | '> Verifying built-v6.3.1-macos-x64...', 177 | 'verify', 178 | '> Uploading built-v6.3.1-macos-x64...', 179 | 'getRelease v1337.2', 180 | 'getReleaseDraft v1337.2', 181 | 'createRelease v1337.2', 182 | 'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-macos-x64"},{"name":"uploaded-v1337.2-node-v4.4.7-macos-x64"}]} uploaded-v1337.2-node-v6.3.1-macos-x64' 183 | ]; 184 | for (let i = 0; i < actions.length; i += 1) { 185 | t.is(actions[i] + ` [[[${i}]]]`, mustBe[i] + ` [[[${i}]]]`); 186 | } 187 | t.is(actions.length, mustBe.length); 188 | }); 189 | -------------------------------------------------------------------------------- /patches/backport.R00000.patch: -------------------------------------------------------------------------------- 1 | commit b324d0bb99045fcfe80397a978eb2ce29af4990f 2 | Author: igorklopov 3 | Date: Mon Aug 17 11:31:50 2015 +0400 4 | 5 | some older revisions mixed together 6 | 7 | diff --git a/src/code-stubs.cc b/src/code-stubs.cc 8 | index 0e68ab8..92aca16 100644 9 | --- node/deps/v8/src/code-stubs.cc 10 | +++ node/deps/v8/src/code-stubs.cc 11 | @@ -252,6 +252,172 @@ void CodeStub::PrintName(OStream& os) const { // NOLINT 12 | } 13 | 14 | 15 | +void CheckCodeStub(CodeStub* pstub, CodeStub::Major MajorKey, int MinorKey) { 16 | + if (pstub->MajorKey() != MajorKey) fprintf(stderr, "MajorKey %d != %d in %s\n", pstub->MajorKey(), MajorKey, pstub->MajorName(MajorKey, false)); 17 | + if (pstub->MinorKey() != MinorKey) fprintf(stderr, "MinorKey %d != %d in %s\n", pstub->MinorKey(), MinorKey, pstub->MajorName(MajorKey, false)); 18 | + // if (pstub->MajorKey() == MajorKey) fprintf(stderr, "correct MajorKey in %s\n", pstub->MajorName(MajorKey, false)); 19 | + // if (pstub->MinorKey() == MinorKey) fprintf(stderr, "correct MinorKey in %s\n", pstub->MajorName(MajorKey, false)); 20 | +} 21 | + 22 | + 23 | +void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out, 24 | + DispatchedCall call) { 25 | + CodeStub::Major MajorKey = MajorKeyFromKey(key); 26 | + int MinorKey = MinorKeyFromKey(key); 27 | + switch (MajorKey) { 28 | + case CEntry: { 29 | + // int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0; 30 | + int result_size = (MinorKey & 0x02) ? 2 : 1; 31 | + // return result | ((result_size_ == 1) ? 0 : 2); 32 | + SaveFPRegsMode save_doubles = (MinorKey & 0x01) ? kSaveFPRegs : kDontSaveFPRegs; 33 | + CEntryStub stub(isolate, result_size, save_doubles); 34 | + CodeStub* pstub = &stub; 35 | + CheckCodeStub(pstub, MajorKey, MinorKey); 36 | + call(pstub, value_out); 37 | + break; 38 | + } 39 | + case CallConstruct: { 40 | + // int MinorKey() const { return flags_; } 41 | + CallConstructorFlags flags = (CallConstructorFlags) MinorKey; 42 | + CallConstructStub stub(isolate, flags); 43 | + CodeStub* pstub = &stub; 44 | + CheckCodeStub(pstub, MajorKey, MinorKey); 45 | + call(pstub, value_out); 46 | + break; 47 | + } 48 | + case FastNewContext: { 49 | + // int NotMissMinorKey() const V8_OVERRIDE { return slots_; } 50 | + int slots = MinorKey; 51 | + FastNewContextStub stub(isolate, slots); 52 | + CodeStub* pstub = &stub; 53 | + CheckCodeStub(pstub, MajorKey, MinorKey); 54 | + call(pstub, value_out); 55 | + break; 56 | + } 57 | + case FastNewClosure: { 58 | + // class StrictModeBits: public BitField {}; 59 | + StrictMode strict_mode = (StrictMode) (MinorKey & 0x01); 60 | + // class IsGeneratorBits: public BitField {}; 61 | + bool is_generator = MinorKey & 0x02; 62 | + FastNewClosureStub stub(isolate, strict_mode, is_generator); 63 | + CodeStub* pstub = &stub; 64 | + CheckCodeStub(pstub, MajorKey, MinorKey); 65 | + call(pstub, value_out); 66 | + break; 67 | + } 68 | + case RecordWrite: { 69 | + #if V8_TARGET_ARCH_IA32 70 | + // class ObjectBits: public BitField {}; 71 | + Register object = Register::from_code(MinorKey & 0x07); 72 | + // class ValueBits: public BitField {}; 73 | + Register value = Register::from_code((MinorKey >> 3) & 0x07); 74 | + // class AddressBits: public BitField {}; 75 | + Register address = Register::from_code((MinorKey >> 6) & 0x07); 76 | + // class RememberedSetActionBits: public BitField {}; 77 | + RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 9) & 0x01); 78 | + // class SaveFPRegsModeBits: public BitField {}; 79 | + SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 10) & 0x01); 80 | + RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode); 81 | + #endif 82 | + #if V8_TARGET_ARCH_X64 83 | + // class ObjectBits: public BitField {}; 84 | + Register object = Register::from_code(MinorKey & 0x0F); 85 | + // class ValueBits: public BitField {}; 86 | + Register value = Register::from_code((MinorKey >> 4) & 0x0F); 87 | + // class AddressBits: public BitField {}; 88 | + Register address = Register::from_code((MinorKey >> 8) & 0x0F); 89 | + // class RememberedSetActionBits: public BitField {}; 90 | + RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 12) & 0x01); 91 | + // class SaveFPRegsModeBits: public BitField {}; 92 | + SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 13) & 0x01); 93 | + RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode); 94 | + #endif 95 | + CodeStub* pstub = &stub; 96 | + CheckCodeStub(pstub, MajorKey, MinorKey); 97 | + call(pstub, value_out); 98 | + break; 99 | + } 100 | + case ToNumber: { 101 | + ToNumberStub stub(isolate); 102 | + CodeStub* pstub = &stub; 103 | + CheckCodeStub(pstub, MajorKey, MinorKey); 104 | + call(pstub, value_out); 105 | + break; 106 | + } 107 | + case ArgumentsAccess: { 108 | + // int MinorKey() const { return type_; } 109 | + ArgumentsAccessStub::Type type = (ArgumentsAccessStub::Type) MinorKey; 110 | + ArgumentsAccessStub stub(isolate, type); 111 | + CodeStub* pstub = &stub; 112 | + CheckCodeStub(pstub, MajorKey, MinorKey); 113 | + call(pstub, value_out); 114 | + break; 115 | + } 116 | + case FastCloneShallowArray: { 117 | + // class AllocationSiteModeBits: public BitField {}; 118 | + AllocationSiteMode allocation_site_mode = (AllocationSiteMode) (MinorKey & 0x01); 119 | + FastCloneShallowArrayStub stub(isolate, allocation_site_mode); 120 | + CodeStub* pstub = &stub; 121 | + CheckCodeStub(pstub, MajorKey, MinorKey); 122 | + call(pstub, value_out); 123 | + break; 124 | + } 125 | + case StoreArrayLiteralElement: { 126 | + StoreArrayLiteralElementStub stub(isolate); 127 | + CodeStub* pstub = &stub; 128 | + CheckCodeStub(pstub, MajorKey, MinorKey); 129 | + call(pstub, value_out); 130 | + break; 131 | + } 132 | + case CallFunction: { 133 | + // class FlagBits: public BitField {}; 134 | + CallFunctionFlags flags = (CallFunctionFlags) (MinorKey & 0x03); 135 | + // class ArgcBits : public BitField {}; 136 | + unsigned argc = MinorKey >> 2; 137 | + CallFunctionStub stub(isolate, argc, flags); 138 | + CodeStub* pstub = &stub; 139 | + CheckCodeStub(pstub, MajorKey, MinorKey); 140 | + call(pstub, value_out); 141 | + break; 142 | + } 143 | + case Instanceof: { 144 | + // int MinorKey() const { return static_cast(flags_); } 145 | + InstanceofStub::Flags flags = (InstanceofStub::Flags) MinorKey; 146 | + InstanceofStub stub(isolate, flags); 147 | + CodeStub* pstub = &stub; 148 | + CheckCodeStub(pstub, MajorKey, MinorKey); 149 | + call(pstub, value_out); 150 | + break; 151 | + } 152 | + case NUMBER_OF_IDS: 153 | + UNREACHABLE(); 154 | + case NoCache: 155 | + *value_out = NULL; 156 | + break; 157 | + default: { 158 | + fprintf(stderr, "unhandled MajorKey: %s (%d)\n", MajorName(MajorKey, false), MajorKey); 159 | + UNREACHABLE(); 160 | + } 161 | + } 162 | +} 163 | + 164 | + 165 | +void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) { 166 | + Handle* code_out = reinterpret_cast*>(value_out); 167 | + // Code stubs with special cache cannot be recreated from stub key. 168 | + *code_out = stub->UseSpecialCache() ? Handle() : stub->GetCode(); 169 | +} 170 | + 171 | + 172 | +MaybeHandle CodeStub::GetCode(Isolate* isolate, uint32_t key) { 173 | + HandleScope scope(isolate); 174 | + Handle code; 175 | + void** value_out = reinterpret_cast(&code); 176 | + Dispatch(isolate, key, value_out, &GetCodeDispatchCall); 177 | + return scope.CloseAndEscape(code); 178 | +} 179 | + 180 | + 181 | // static 182 | void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) { 183 | // Generate the uninitialized versions of the stub. 184 | diff --git a/src/code-stubs.h b/src/code-stubs.h 185 | index c1d051b..9cc12df 100644 186 | --- node/deps/v8/src/code-stubs.h 187 | +++ node/deps/v8/src/code-stubs.h 188 | @@ -179,6 +179,8 @@ class CodeStub BASE_EMBEDDED { 189 | // Lookup the code in the (possibly custom) cache. 190 | bool FindCodeInCache(Code** code_out); 191 | 192 | + static MaybeHandle GetCode(Isolate* isolate, uint32_t key); 193 | + 194 | // Returns information for computing the number key. 195 | virtual Major MajorKey() const = 0; 196 | virtual int MinorKey() const = 0; 197 | @@ -242,6 +244,14 @@ class CodeStub BASE_EMBEDDED { 198 | // If a stub uses a special cache override this. 199 | virtual bool UseSpecialCache() { return false; } 200 | 201 | + // We use this dispatch to statically instantiate the correct code stub for 202 | + // the given stub key and call the passed function with that code stub. 203 | + typedef void (*DispatchedCall)(CodeStub* stub, void** value_out); 204 | + static void Dispatch(Isolate* isolate, uint32_t key, void** value_out, 205 | + DispatchedCall call); 206 | + 207 | + static void GetCodeDispatchCall(CodeStub* stub, void** value_out); 208 | + 209 | STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits)); 210 | class MajorKeyBits: public BitField {}; 211 | class MinorKeyBits: public BitField 3 | Date: Fri Oct 31 14:43:21 2014 +0000 4 | 5 | Break allocations in the code serializer into correct chunk sizes. 6 | 7 | This change has been inspired by Slava Chigrin (https://codereview.chromium.org/689663002/) 8 | 9 | R=mvstanton@chromium.org, vchigrin@yandex-team.ru 10 | 11 | Review URL: https://codereview.chromium.org/686103004 12 | 13 | Cr-Commit-Position: refs/heads/master@{#25039} 14 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25039 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 15 | 16 | diff --git a/src/heap/heap.cc b/src/heap/heap.cc 17 | index 94c8937..93e00d2 100644 18 | --- node/deps/v8/src/heap/heap.cc 19 | +++ node/deps/v8/src/heap/heap.cc 20 | @@ -939,6 +939,8 @@ bool Heap::ReserveSpace(Reservation* reservations) { 21 | for (auto& chunk : *reservation) { 22 | AllocationResult allocation; 23 | int size = chunk.size; 24 | + DCHECK_LE(size, MemoryAllocator::PageAreaSize( 25 | + static_cast(space))); 26 | if (space == NEW_SPACE) { 27 | allocation = new_space()->AllocateRaw(size); 28 | } else { 29 | diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc 30 | index 85281aa..430f31d 100644 31 | --- node/deps/v8/src/heap/spaces.cc 32 | +++ node/deps/v8/src/heap/spaces.cc 33 | @@ -892,19 +892,15 @@ void MemoryChunk::IncrementLiveBytesFromMutator(Address address, int by) { 34 | // ----------------------------------------------------------------------------- 35 | // PagedSpace implementation 36 | 37 | -PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id, 38 | +PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace space, 39 | Executability executable) 40 | - : Space(heap, id, executable), 41 | + : Space(heap, space, executable), 42 | free_list_(this), 43 | swept_precisely_(true), 44 | unswept_free_bytes_(0), 45 | end_of_unswept_pages_(NULL), 46 | emergency_memory_(NULL) { 47 | - if (id == CODE_SPACE) { 48 | - area_size_ = heap->isolate()->memory_allocator()->CodePageAreaSize(); 49 | - } else { 50 | - area_size_ = Page::kPageSize - Page::kObjectStartOffset; 51 | - } 52 | + area_size_ = MemoryAllocator::PageAreaSize(space); 53 | max_capacity_ = 54 | (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) * AreaSize(); 55 | accounting_stats_.Clear(); 56 | diff --git a/src/heap/spaces.h b/src/heap/spaces.h 57 | index 5be9c3a..1944464 100644 58 | --- node/deps/v8/src/heap/spaces.h 59 | +++ node/deps/v8/src/heap/spaces.h 60 | @@ -1104,6 +1104,12 @@ class MemoryAllocator { 61 | return CodePageAreaEndOffset() - CodePageAreaStartOffset(); 62 | } 63 | 64 | + static int PageAreaSize(AllocationSpace space) { 65 | + DCHECK_NE(LO_SPACE, space); 66 | + return (space == CODE_SPACE) ? CodePageAreaSize() 67 | + : Page::kMaxRegularHeapObjectSize; 68 | + } 69 | + 70 | MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm, 71 | Address start, size_t commit_size, 72 | size_t reserved_size); 73 | diff --git a/src/serialize.cc b/src/serialize.cc 74 | index 86045d3..df62adb 100644 75 | --- node/deps/v8/src/serialize.cc 76 | +++ node/deps/v8/src/serialize.cc 77 | @@ -1258,10 +1258,15 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) 78 | external_reference_encoder_(new ExternalReferenceEncoder(isolate)), 79 | root_index_map_(isolate), 80 | code_address_map_(NULL), 81 | + large_objects_total_size_(0), 82 | seen_large_objects_index_(0) { 83 | // The serializer is meant to be used only to generate initial heap images 84 | // from a context in which there is only one isolate. 85 | - for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0; 86 | + for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { 87 | + pending_chunk_[i] = 0; 88 | + max_chunk_size_[i] = static_cast( 89 | + MemoryAllocator::PageAreaSize(static_cast(i))); 90 | + } 91 | } 92 | 93 | 94 | @@ -1336,8 +1341,7 @@ void Serializer::VisitPointers(Object** start, Object** end) { 95 | 96 | 97 | void Serializer::FinalizeAllocation() { 98 | - DCHECK_EQ(0, completed_chunks_[LO_SPACE].length()); // Not yet finalized. 99 | - for (int i = 0; i < kNumberOfSpaces; i++) { 100 | + for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { 101 | // Complete the last pending chunk and if there are no completed chunks, 102 | // make sure there is at least one empty chunk. 103 | if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { 104 | @@ -1906,17 +1910,17 @@ AllocationSpace Serializer::SpaceOfObject(HeapObject* object) { 105 | uint32_t Serializer::AllocateLargeObject(int size) { 106 | // Large objects are allocated one-by-one when deserializing. We do not 107 | // have to keep track of multiple chunks. 108 | - pending_chunk_[LO_SPACE] += size; 109 | + large_objects_total_size_ += size; 110 | return seen_large_objects_index_++; 111 | } 112 | 113 | 114 | uint32_t Serializer::Allocate(int space, int size) { 115 | CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); 116 | - DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize); 117 | + DCHECK(size > 0 && size <= static_cast(max_chunk_size(space))); 118 | uint32_t new_chunk_size = pending_chunk_[space] + size; 119 | uint32_t allocation; 120 | - if (new_chunk_size > static_cast(Page::kMaxRegularHeapObjectSize)) { 121 | + if (new_chunk_size > max_chunk_size(space)) { 122 | // The new chunk size would not fit onto a single page. Complete the 123 | // current chunk and start a new one. 124 | completed_chunks_[space].Add(pending_chunk_[space]); 125 | @@ -1929,15 +1933,6 @@ BackReference Serializer::Allocate(AllocationSpace space, int size) { 126 | } 127 | 128 | 129 | -int Serializer::SpaceAreaSize(int space) { 130 | - if (space == CODE_SPACE) { 131 | - return isolate_->memory_allocator()->CodePageAreaSize(); 132 | - } else { 133 | - return Page::kPageSize - Page::kObjectStartOffset; 134 | - } 135 | -} 136 | - 137 | - 138 | void Serializer::Pad() { 139 | // The non-branching GetInt will read up to 3 bytes too far, so we need 140 | // to pad the snapshot to make sure we don't read over the end. 141 | @@ -2273,9 +2268,6 @@ SerializedCodeData::SerializedCodeData(const List& payload, 142 | for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { 143 | Vector chunks = cs->FinalAllocationChunks(i); 144 | for (int j = 0; j < chunks.length(); j++) { 145 | - DCHECK(i == LO_SPACE || 146 | - chunks[j] <= 147 | - static_cast(Page::kMaxRegularHeapObjectSize)); 148 | uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | 149 | IsLastChunkBits::encode(j == chunks.length() - 1); 150 | reservations.Add(chunk); 151 | diff --git a/src/serialize.h b/src/serialize.h 152 | index 2aa55ea..9c56118 100644 153 | --- node/deps/v8/src/serialize.h 154 | +++ node/deps/v8/src/serialize.h 155 | @@ -404,8 +404,6 @@ class Deserializer: public SerializerDeserializer { 156 | void AddReservation(int space, uint32_t chunk) { 157 | DCHECK(space >= 0); 158 | DCHECK(space < kNumberOfSpaces); 159 | - DCHECK(space == LO_SPACE || 160 | - chunk <= static_cast(Page::kMaxRegularHeapObjectSize)); 161 | Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c); 162 | } 163 | 164 | @@ -498,9 +496,12 @@ class Serializer : public SerializerDeserializer { 165 | void FinalizeAllocation(); 166 | 167 | Vector FinalAllocationChunks(int space) const { 168 | - DCHECK_EQ(1, completed_chunks_[LO_SPACE].length()); // Already finalized. 169 | - DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks. 170 | - return completed_chunks_[space].ToConstVector(); 171 | + if (space == LO_SPACE) { 172 | + return Vector(&large_objects_total_size_, 1); 173 | + } else { 174 | + DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks. 175 | + return completed_chunks_[space].ToConstVector(); 176 | + } 177 | } 178 | 179 | Isolate* isolate() const { return isolate_; } 180 | @@ -496,20 +496,25 @@ 181 | return external_reference_encoder_->Encode(addr); 182 | } 183 | 184 | - int SpaceAreaSize(int space); 185 | - 186 | // Some roots should not be serialized, because their actual value depends on 187 | // absolute addresses and they are reset after deserialization, anyway. 188 | bool ShouldBeSkipped(Object** current); 189 | 190 | + uint32_t max_chunk_size(int space) const { 191 | + DCHECK_LE(0, space); 192 | + DCHECK_LT(space, kNumberOfSpaces); 193 | + return max_chunk_size_[space]; 194 | + } 195 | + 196 | Isolate* isolate_; 197 | 198 | // Objects from the same space are put into chunks for bulk-allocation 199 | // when deserializing. We have to make sure that each chunk fits into a 200 | // page. So we track the chunk size in pending_chunk_ of a space, but 201 | // when it exceeds a page, we complete the current chunk and start a new one. 202 | - uint32_t pending_chunk_[kNumberOfSpaces]; 203 | - List completed_chunks_[kNumberOfSpaces]; 204 | + uint32_t pending_chunk_[kNumberOfPreallocatedSpaces]; 205 | + List completed_chunks_[kNumberOfPreallocatedSpaces]; 206 | + uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces]; 207 | 208 | SnapshotByteSink* sink_; 209 | ExternalReferenceEncoder* external_reference_encoder_; 210 | @@ -529,6 +534,7 @@ 211 | CodeAddressMap* code_address_map_; 212 | // We map serialized large objects to indexes for back-referencing. 213 | uint32_t seen_large_objects_index_; 214 | + uint32_t large_objects_total_size_; 215 | DISALLOW_COPY_AND_ASSIGN(Serializer); 216 | }; 217 | 218 | -------------------------------------------------------------------------------- /patches/backport.R32768.patch: -------------------------------------------------------------------------------- 1 | commit eb67f85439dcc273501e9fba5a9e883585505aa8 2 | Author: adamk 3 | Date: Thu Dec 10 11:18:54 2015 -0800 4 | 5 | Fix FuncNameInferrer usage in ParseAssignmentExpression 6 | 7 | Without this fix, AssignmentExpressions that happen to be arrow functions 8 | would lead to unbalanced Enter/Leave calls on the fni_, causing thrashing 9 | while trying to infer function names. Symptoms include slow parsing 10 | or OOM (when we create too many AstConsStrings). 11 | 12 | To try to keep this from happening in the future, added an RAII helper 13 | class to handle Entering/Leaving FNI state. 14 | 15 | The included regression test crashes on my workstation without the patch. 16 | Note that it's too slow in debug mode (as well as under TurboFan), 17 | so I've skipped it there. 18 | 19 | BUG=v8:4595 20 | LOG=y 21 | 22 | Review URL: https://codereview.chromium.org/1507283003 23 | 24 | Cr-Commit-Position: refs/heads/master@{#32768} 25 | 26 | diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h 27 | index 8b077f9..1be6332 100644 28 | --- node/deps/v8/src/func-name-inferrer.h 29 | +++ node/deps/v8/src/func-name-inferrer.h 30 | @@ -28,21 +28,33 @@ class FunctionLiteral; 31 | // a name. 32 | class FuncNameInferrer : public ZoneObject { 33 | public: 34 | FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone); 35 | 36 | + // To enter function name inference state, put a FuncNameInferrer::State 37 | + // on the stack. 38 | + class State { 39 | + public: 40 | + explicit State(FuncNameInferrer* fni) : fni_(fni) { 41 | + if (fni_ != nullptr) fni_->Enter(); 42 | + } 43 | + ~State() { 44 | + if (fni_ != nullptr) fni_->Leave(); 45 | + } 46 | + 47 | + private: 48 | + FuncNameInferrer* fni_; 49 | + 50 | + DISALLOW_COPY_AND_ASSIGN(State); 51 | + }; 52 | + 53 | // Returns whether we have entered name collection state. 54 | bool IsOpen() const { return !entries_stack_.is_empty(); } 55 | 56 | // Pushes an enclosing the name of enclosing function onto names stack. 57 | void PushEnclosingName(const AstRawString* name); 58 | 59 | - // Enters name collection state. 60 | - void Enter() { 61 | - entries_stack_.Add(names_stack_.length(), zone()); 62 | - } 63 | - 64 | // Pushes an encountered name onto names stack when in collection state. 65 | void PushLiteralName(const AstRawString* name); 66 | 67 | void PushVariableName(const AstRawString* name); 68 | 69 | @@ -65,18 +77,10 @@ class FuncNameInferrer : public ZoneObject { 70 | if (!funcs_to_infer_.is_empty()) { 71 | InferFunctionsNames(); 72 | } 73 | } 74 | 75 | - // Leaves names collection state. 76 | - void Leave() { 77 | - DCHECK(IsOpen()); 78 | - names_stack_.Rewind(entries_stack_.RemoveLast()); 79 | - if (entries_stack_.is_empty()) 80 | - funcs_to_infer_.Clear(); 81 | - } 82 | - 83 | private: 84 | enum NameType { 85 | kEnclosingConstructorName, 86 | kLiteralName, 87 | kVariableName 88 | @@ -85,10 +89,18 @@ class FuncNameInferrer : public ZoneObject { 89 | Name(const AstRawString* name, NameType type) : name(name), type(type) {} 90 | const AstRawString* name; 91 | NameType type; 92 | }; 93 | 94 | + void Enter() { entries_stack_.Add(names_stack_.length(), zone()); } 95 | + 96 | + void Leave() { 97 | + DCHECK(IsOpen()); 98 | + names_stack_.Rewind(entries_stack_.RemoveLast()); 99 | + if (entries_stack_.is_empty()) funcs_to_infer_.Clear(); 100 | + } 101 | + 102 | Zone* zone() const { return zone_; } 103 | 104 | // Constructs a full name in dotted notation from gathered names. 105 | const AstString* MakeNameFromStack(); 106 | 107 | diff --git a/src/parser.cc b/src/parser.cc 108 | index aa0ec10..b09286b 100644 109 | --- node/deps/v8/src/parser.cc 110 | +++ node/deps/v8/src/parser.cc 111 | @@ -2466,11 +2466,11 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, 112 | 113 | bool first_declaration = true; 114 | int bindings_start = peek_position(); 115 | bool is_for_iteration_variable; 116 | do { 117 | - if (fni_ != NULL) fni_->Enter(); 118 | + FuncNameInferrer::State fni_state(fni_); 119 | 120 | // Parse name. 121 | if (!first_declaration) Consume(Token::COMMA); 122 | 123 | Expression* pattern; 124 | @@ -2541,11 +2541,10 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, 125 | // Make sure that 'const x' and 'let x' initialize 'x' to undefined. 126 | if (value == NULL && parsing_result->descriptor.needs_init) { 127 | value = GetLiteralUndefined(position()); 128 | } 129 | 130 | - if (single_name && fni_ != NULL) fni_->Leave(); 131 | parsing_result->declarations.Add(DeclarationParsingResult::Declaration( 132 | pattern, initializer_position, value)); 133 | first_declaration = false; 134 | } while (peek() == Token::COMMA); 135 | 136 | @@ -4504,11 +4503,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, 137 | Expect(Token::LBRACE, CHECK_OK); 138 | 139 | const bool has_extends = extends != nullptr; 140 | while (peek() != Token::RBRACE) { 141 | if (Check(Token::SEMICOLON)) continue; 142 | - if (fni_ != NULL) fni_->Enter(); 143 | + FuncNameInferrer::State fni_state(fni_); 144 | const bool in_class = true; 145 | const bool is_static = false; 146 | bool is_computed_name = false; // Classes do not care about computed 147 | // property names here. 148 | ExpressionClassifier classifier; 149 | @@ -4522,14 +4521,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, 150 | DCHECK_NOT_NULL(constructor); 151 | } else { 152 | properties->Add(property, zone()); 153 | } 154 | 155 | - if (fni_ != NULL) { 156 | - fni_->Infer(); 157 | - fni_->Leave(); 158 | - } 159 | + if (fni_ != NULL) fni_->Infer(); 160 | } 161 | 162 | Expect(Token::RBRACE, CHECK_OK); 163 | int end_pos = scanner()->location().end_pos; 164 | 165 | diff --git a/src/preparser.h b/src/preparser.h 166 | index d9ef1ea..4141cd6 100644 167 | --- node/deps/v8/src/preparser.h 168 | +++ node/deps/v8/src/preparser.h 169 | @@ -2646,11 +2646,11 @@ typename ParserBase::ExpressionT ParserBase::ParseObjectLiteral( 170 | ObjectLiteralChecker checker(this); 171 | 172 | Expect(Token::LBRACE, CHECK_OK); 173 | 174 | while (peek() != Token::RBRACE) { 175 | - if (fni_ != nullptr) fni_->Enter(); 176 | + FuncNameInferrer::State fni_state(fni_); 177 | 178 | const bool in_class = false; 179 | const bool is_static = false; 180 | const bool has_extends = false; 181 | bool is_computed_name = false; 182 | @@ -2677,14 +2677,11 @@ typename ParserBase::ExpressionT ParserBase::ParseObjectLiteral( 183 | if (peek() != Token::RBRACE) { 184 | // Need {} because of the CHECK_OK macro. 185 | Expect(Token::COMMA, CHECK_OK); 186 | } 187 | 188 | - if (fni_ != nullptr) { 189 | - fni_->Infer(); 190 | - fni_->Leave(); 191 | - } 192 | + if (fni_ != nullptr) fni_->Infer(); 193 | } 194 | Expect(Token::RBRACE, CHECK_OK); 195 | 196 | // Computation of literal_index must happen before pre parse bailout. 197 | int literal_index = function_state_->NextMaterializedLiteralIndex(); 198 | @@ -2781,11 +2778,11 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, 199 | 200 | if (peek() == Token::YIELD && is_generator()) { 201 | return this->ParseYieldExpression(classifier, ok); 202 | } 203 | 204 | - if (fni_ != NULL) fni_->Enter(); 205 | + FuncNameInferrer::State fni_state(fni_); 206 | ParserBase::Checkpoint checkpoint(this); 207 | ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); 208 | bool parenthesized_formals = peek() == Token::LPAREN; 209 | if (!parenthesized_formals) { 210 | ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); 211 | @@ -2811,21 +2808,23 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, 212 | arrow_formals_classifier.RecordDuplicateFormalParameterError( 213 | duplicate_loc); 214 | } 215 | expression = this->ParseArrowFunctionLiteral( 216 | parsing_state, arrow_formals_classifier, CHECK_OK); 217 | + 218 | + if (fni_ != nullptr) fni_->Infer(); 219 | + 220 | return expression; 221 | } 222 | 223 | // "expression" was not itself an arrow function parameter list, but it might 224 | // form part of one. Propagate speculative formal parameter error locations. 225 | classifier->Accumulate(arrow_formals_classifier, 226 | ExpressionClassifier::StandardProductions | 227 | ExpressionClassifier::FormalParametersProductions); 228 | 229 | if (!Token::IsAssignmentOp(peek())) { 230 | - if (fni_ != NULL) fni_->Leave(); 231 | // Parsed conditional expression only (no assignment). 232 | return expression; 233 | } 234 | 235 | if (!allow_harmony_destructuring()) { 236 | @@ -2871,11 +2870,10 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, 237 | && (!right->IsCall() && !right->IsCallNew())) { 238 | fni_->Infer(); 239 | } else { 240 | fni_->RemoveLastFunction(); 241 | } 242 | - fni_->Leave(); 243 | } 244 | 245 | return factory()->NewAssignment(op, expression, right, pos); 246 | } 247 | 248 | @@ -3324,11 +3322,11 @@ ParserBase::ParseStrongInitializationExpression( 249 | ExpressionClassifier* classifier, bool* ok) { 250 | // InitializationExpression :: (strong mode) 251 | // 'this' '.' IdentifierName '=' AssignmentExpression 252 | // 'this' '[' Expression ']' '=' AssignmentExpression 253 | 254 | - if (fni_ != NULL) fni_->Enter(); 255 | + FuncNameInferrer::State fni_state(fni_); 256 | 257 | Consume(Token::THIS); 258 | int pos = position(); 259 | function_state_->set_this_location(scanner()->location()); 260 | ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); 261 | @@ -3383,11 +3381,10 @@ ParserBase::ParseStrongInitializationExpression( 262 | if (!right->IsCall() && !right->IsCallNew()) { 263 | fni_->Infer(); 264 | } else { 265 | fni_->RemoveLastFunction(); 266 | } 267 | - fni_->Leave(); 268 | } 269 | 270 | if (function_state_->return_location().IsValid()) { 271 | ReportMessageAt(function_state_->return_location(), 272 | MessageTemplate::kStrongConstructorReturnMisplaced); 273 | -------------------------------------------------------------------------------- /patches/backport.R24266.patch: -------------------------------------------------------------------------------- 1 | commit ad24cdae728fc34b23e74a22543702de3ae477d1 2 | Author: yangguo@chromium.org 3 | Date: Mon Sep 29 07:53:22 2014 +0000 4 | 5 | Do not serialize non-lazy compiled function literals. 6 | 7 | ... and some small refactorings. 8 | 9 | R=mvstanton@chromium.org 10 | 11 | Review URL: https://codereview.chromium.org/594513002 12 | 13 | git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24266 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 14 | 15 | diff --git a/src/serialize.cc b/src/serialize.cc 16 | index a2dde9b..9d59b6f 100644 17 | --- node/deps/v8/src/serialize.cc 18 | +++ node/deps/v8/src/serialize.cc 19 | @@ -1846,7 +1846,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate, 20 | SnapshotByteSink* sink = FLAG_trace_code_serializer 21 | ? static_cast(&debug_sink) 22 | : static_cast(&list_sink); 23 | - CodeSerializer cs(isolate, sink, *source); 24 | + CodeSerializer cs(isolate, sink, *source, info->code()); 25 | DisallowHeapAllocation no_gc; 26 | Object** location = Handle::cast(info).location(); 27 | cs.VisitPointer(location); 28 | @@ -1867,31 +1867,25 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate, 29 | 30 | void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, 31 | WhereToPoint where_to_point, int skip) { 32 | - CHECK(o->IsHeapObject()); 33 | HeapObject* heap_object = HeapObject::cast(o); 34 | 35 | - // The code-caches link to context-specific code objects, which 36 | - // the startup and context serializes cannot currently handle. 37 | - DCHECK(!heap_object->IsMap() || 38 | - Map::cast(heap_object)->code_cache() == 39 | - heap_object->GetHeap()->empty_fixed_array()); 40 | - 41 | int root_index; 42 | if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { 43 | PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); 44 | return; 45 | } 46 | 47 | - // TODO(yangguo) wire up global object. 48 | - // TODO(yangguo) We cannot deal with different hash seeds yet. 49 | - DCHECK(!heap_object->IsHashTable()); 50 | - 51 | if (address_mapper_.IsMapped(heap_object)) { 52 | SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, 53 | skip); 54 | return; 55 | } 56 | 57 | + if (skip != 0) { 58 | + sink_->Put(kSkip, "SkipFromSerializeObject"); 59 | + sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); 60 | + } 61 | + 62 | if (heap_object->IsCode()) { 63 | Code* code_object = Code::cast(heap_object); 64 | switch (code_object->kind()) { 65 | @@ -1901,34 +1895,42 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, 66 | case Code::NUMBER_OF_KINDS: // Pseudo enum value. 67 | CHECK(false); 68 | case Code::BUILTIN: 69 | - SerializeBuiltin(code_object, how_to_code, where_to_point, skip); 70 | + SerializeBuiltin(code_object, how_to_code, where_to_point); 71 | return; 72 | case Code::STUB: 73 | - SerializeCodeStub(code_object, how_to_code, where_to_point, skip); 74 | + SerializeCodeStub(code_object, how_to_code, where_to_point); 75 | return; 76 | #define IC_KIND_CASE(KIND) case Code::KIND: 77 | IC_KIND_LIST(IC_KIND_CASE) 78 | #undef IC_KIND_CASE 79 | + SerializeHeapObject(code_object, how_to_code, where_to_point); 80 | + return; 81 | // TODO(yangguo): add special handling to canonicalize ICs. 82 | case Code::FUNCTION: 83 | - SerializeHeapObject(code_object, how_to_code, where_to_point, skip); 84 | + SerializeHeapObject(code_object, how_to_code, where_to_point); 85 | return; 86 | } 87 | } 88 | 89 | if (heap_object == source_) { 90 | - SerializeSourceObject(how_to_code, where_to_point, skip); 91 | + SerializeSourceObject(how_to_code, where_to_point); 92 | return; 93 | } 94 | 95 | - SerializeHeapObject(heap_object, how_to_code, where_to_point, skip); 96 | + // Past this point we should not see any (context-specific) maps anymore. 97 | + CHECK(!heap_object->IsMap()); 98 | + // There should be no references to the global object embedded. 99 | + CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject()); 100 | + // There should be no hash table embedded. They would require rehashing. 101 | + CHECK(!heap_object->IsHashTable()); 102 | + 103 | + SerializeHeapObject(heap_object, how_to_code, where_to_point); 104 | } 105 | 106 | 107 | void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, 108 | HowToCode how_to_code, 109 | - WhereToPoint where_to_point, 110 | - int skip) { 111 | + WhereToPoint where_to_point) { 112 | if (heap_object->IsScript()) { 113 | // The wrapper cache uses a Foreign object to point to a global handle. 114 | // However, the object visitor expects foreign objects to point to external 115 | @@ -1936,11 +1946,6 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, 116 | Script::cast(heap_object)->ClearWrapperCache(); 117 | } 118 | 119 | - if (skip != 0) { 120 | - sink_->Put(kSkip, "SkipFromSerializeObject"); 121 | - sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); 122 | - } 123 | - 124 | if (FLAG_trace_code_serializer) { 125 | PrintF("Encoding heap object: "); 126 | heap_object->ShortPrint(); 127 | @@ -1955,12 +1960,7 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, 128 | 129 | 130 | void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, 131 | - WhereToPoint where_to_point, int skip) { 132 | - if (skip != 0) { 133 | - sink_->Put(kSkip, "SkipFromSerializeBuiltin"); 134 | - sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); 135 | - } 136 | - 137 | + WhereToPoint where_to_point) { 138 | DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || 139 | (how_to_code == kPlain && where_to_point == kInnerPointer) || 140 | (how_to_code == kFromCode && where_to_point == kInnerPointer)); 141 | @@ -1979,18 +1979,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, 142 | 143 | 144 | void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code, 145 | - WhereToPoint where_to_point, int skip) { 146 | + WhereToPoint where_to_point) { 147 | DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || 148 | (how_to_code == kPlain && where_to_point == kInnerPointer) || 149 | (how_to_code == kFromCode && where_to_point == kInnerPointer)); 150 | uint32_t stub_key = stub->stub_key(); 151 | DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); 152 | 153 | - if (skip != 0) { 154 | - sink_->Put(kSkip, "SkipFromSerializeCodeStub"); 155 | - sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub"); 156 | - } 157 | - 158 | int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; 159 | 160 | if (FLAG_trace_code_serializer) { 161 | @@ -2017,16 +2012,8 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { 162 | 163 | 164 | void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, 165 | - WhereToPoint where_to_point, 166 | - int skip) { 167 | - if (skip != 0) { 168 | - sink_->Put(kSkip, "SkipFromSerializeSourceObject"); 169 | - sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject"); 170 | - } 171 | - 172 | - if (FLAG_trace_code_serializer) { 173 | - PrintF("Encoding source object\n"); 174 | - } 175 | + WhereToPoint where_to_point) { 176 | + if (FLAG_trace_code_serializer) PrintF("Encoding source object\n"); 177 | 178 | DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); 179 | sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); 180 | diff --git a/src/serialize.h b/src/serialize.h 181 | index b6ad82c..616f8f1 100644 182 | --- node/deps/v8/src/serialize.h 183 | +++ node/deps/v8/src/serialize.h 184 | @@ -577,19 +577,10 @@ class StartupSerializer : public Serializer { 185 | 186 | class CodeSerializer : public Serializer { 187 | public: 188 | - CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source) 189 | - : Serializer(isolate, sink), source_(source) { 190 | - set_root_index_wave_front(Heap::kStrongRootListLength); 191 | - InitializeCodeAddressMap(); 192 | - } 193 | - 194 | static ScriptData* Serialize(Isolate* isolate, 195 | Handle info, 196 | Handle source); 197 | 198 | - virtual void SerializeObject(Object* o, HowToCode how_to_code, 199 | - WhereToPoint where_to_point, int skip); 200 | - 201 | static Handle Deserialize(Isolate* isolate, 202 | ScriptData* data, 203 | Handle source); 204 | @@ -605,18 +596,29 @@ class CodeSerializer : public Serializer { 205 | List* stub_keys() { return &stub_keys_; } 206 | 207 | private: 208 | + CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source, 209 | + Code* main_code) 210 | + : Serializer(isolate, sink), source_(source), main_code_(main_code) { 211 | + set_root_index_wave_front(Heap::kStrongRootListLength); 212 | + InitializeCodeAddressMap(); 213 | + } 214 | + 215 | + virtual void SerializeObject(Object* o, HowToCode how_to_code, 216 | + WhereToPoint where_to_point, int skip); 217 | + 218 | void SerializeBuiltin(Code* builtin, HowToCode how_to_code, 219 | - WhereToPoint where_to_point, int skip); 220 | + WhereToPoint where_to_point); 221 | void SerializeCodeStub(Code* stub, HowToCode how_to_code, 222 | - WhereToPoint where_to_point, int skip); 223 | - void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point, 224 | - int skip); 225 | + WhereToPoint where_to_point); 226 | + void SerializeSourceObject(HowToCode how_to_code, 227 | + WhereToPoint where_to_point); 228 | void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code, 229 | - WhereToPoint where_to_point, int skip); 230 | + WhereToPoint where_to_point); 231 | int AddCodeStubKey(uint32_t stub_key); 232 | 233 | DisallowHeapAllocation no_gc_; 234 | String* source_; 235 | + Code* main_code_; 236 | List stub_keys_; 237 | DISALLOW_COPY_AND_ASSIGN(CodeSerializer); 238 | }; 239 | -------------------------------------------------------------------------------- /patches/node.v0.12.18.cpp.patch: -------------------------------------------------------------------------------- 1 | --- node/deps/v8/include/v8.h 2 | +++ node/deps/v8/include/v8.h 3 | @@ -4826,10 +4826,14 @@ 4 | */ 5 | static void SetFlagsFromCommandLine(int* argc, 6 | char** argv, 7 | bool remove_flags); 8 | 9 | + static void EnableCompilationForSourcelessUse(); 10 | + static void DisableCompilationForSourcelessUse(); 11 | + static void FixSourcelessScript(Isolate* v8_isolate, Local script); 12 | + 13 | /** Get the version string. */ 14 | static const char* GetVersion(); 15 | 16 | /** Callback function for reporting failed access checks.*/ 17 | static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); 18 | --- node/deps/v8/src/api.cc 19 | +++ node/deps/v8/src/api.cc 20 | @@ -391,10 +391,46 @@ 21 | void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 22 | i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 23 | } 24 | 25 | 26 | +bool save_lazy; 27 | +bool save_predictable; 28 | +bool save_serialize_toplevel; 29 | + 30 | + 31 | +void V8::EnableCompilationForSourcelessUse() { 32 | + save_lazy = i::FLAG_lazy; 33 | + i::FLAG_lazy = false; 34 | + save_predictable = i::FLAG_predictable; 35 | + i::FLAG_predictable = true; 36 | + save_serialize_toplevel = i::FLAG_serialize_toplevel; 37 | + i::FLAG_serialize_toplevel = true; 38 | + i::CpuFeatures::Reinitialize(); 39 | + i::CpuFeatures::Probe(true); 40 | +} 41 | + 42 | + 43 | +void V8::DisableCompilationForSourcelessUse() { 44 | + i::FLAG_lazy = save_lazy; 45 | + i::FLAG_predictable = save_predictable; 46 | + i::FLAG_serialize_toplevel = save_serialize_toplevel; 47 | + i::CpuFeatures::Reinitialize(); 48 | + i::CpuFeatures::Probe(false); 49 | +} 50 | + 51 | + 52 | +void V8::FixSourcelessScript(Isolate* v8_isolate, Local script) { 53 | + i::Isolate* isolate = reinterpret_cast(v8_isolate); 54 | + i::Handle object = i::Handle::cast(Utils::OpenHandle(*script)); 55 | + i::Handle function_info( 56 | + i::SharedFunctionInfo::cast(*object), object->GetIsolate()); 57 | + i::Script* s = reinterpret_cast(function_info->script()); 58 | + s->set_source(isolate->heap()->undefined_value()); 59 | +} 60 | + 61 | + 62 | RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 63 | 64 | 65 | RegisteredExtension::RegisteredExtension(Extension* extension) 66 | : extension_(extension) { } 67 | --- node/deps/v8/src/assembler.h 68 | +++ node/deps/v8/src/assembler.h 69 | @@ -196,10 +196,15 @@ 70 | static void PrintFeatures(); 71 | 72 | // Flush instruction cache. 73 | static void FlushICache(void* start, size_t size); 74 | 75 | + static void Reinitialize() { 76 | + supported_ = 0; 77 | + initialized_ = false; 78 | + } 79 | + 80 | private: 81 | // Platform-dependent implementation. 82 | static void ProbeImpl(bool cross_compile); 83 | 84 | static unsigned supported_; 85 | --- node/deps/v8/src/parser.cc 86 | +++ node/deps/v8/src/parser.cc 87 | @@ -4838,10 +4838,11 @@ 88 | return !parser.failed(); 89 | } 90 | 91 | 92 | bool Parser::Parse() { 93 | + if (info()->script()->source()->IsUndefined()) return false; 94 | DCHECK(info()->function() == NULL); 95 | FunctionLiteral* result = NULL; 96 | ast_value_factory_ = info()->ast_value_factory(); 97 | if (ast_value_factory_ == NULL) { 98 | ast_value_factory_ = 99 | --- node/deps/v8/src/serialize.cc 100 | +++ node/deps/v8/src/serialize.cc 101 | @@ -2167,11 +2167,11 @@ 102 | payload->begin(), static_cast(payload->length())); 103 | } 104 | 105 | 106 | bool SerializedCodeData::IsSane(String* source) { 107 | - return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && 108 | + return true && 109 | PayloadLength() >= SharedFunctionInfo::kSize; 110 | } 111 | 112 | 113 | int SerializedCodeData::CheckSum(String* string) { 114 | --- node/lib/child_process.js 115 | +++ node/lib/child_process.js 116 | @@ -579,11 +579,11 @@ 117 | options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] : 118 | [0, 1, 2, 'ipc']; 119 | 120 | options.execPath = options.execPath || process.execPath; 121 | 122 | - return spawn(options.execPath, args, options); 123 | + return exports.spawn(options.execPath, args, options); 124 | }; 125 | 126 | 127 | exports._forkChild = function(fd) { 128 | // set process.send() 129 | --- node/src/env.h 130 | +++ node/src/env.h 131 | @@ -202,10 +202,11 @@ 132 | V(signal_string, "signal") \ 133 | V(size_string, "size") \ 134 | V(smalloc_p_string, "_smalloc_p") \ 135 | V(sni_context_err_string, "Invalid SNI context") \ 136 | V(sni_context_string, "sni_context") \ 137 | + V(sourceless_string, "sourceless") \ 138 | V(speed_string, "speed") \ 139 | V(stack_string, "stack") \ 140 | V(status_code_string, "statusCode") \ 141 | V(status_message_string, "statusMessage") \ 142 | V(status_string, "status") \ 143 | --- node/src/node.cc 144 | +++ node/src/node.cc 145 | @@ -2957,10 +2957,11 @@ 146 | } 147 | 148 | static void PrintHelp(); 149 | 150 | static bool ParseDebugOpt(const char* arg) { 151 | + return false; 152 | const char* port = NULL; 153 | 154 | if (!strcmp(arg, "--debug")) { 155 | use_debug_agent = true; 156 | } else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) { 157 | @@ -3575,14 +3576,10 @@ 158 | // Ignore SIGPIPE 159 | RegisterSignalHandler(SIGPIPE, SIG_IGN); 160 | RegisterSignalHandler(SIGINT, SignalExit, true); 161 | RegisterSignalHandler(SIGTERM, SignalExit, true); 162 | #endif // __POSIX__ 163 | - 164 | - if (!use_debug_agent) { 165 | - RegisterDebugSignalHandler(); 166 | - } 167 | } 168 | 169 | 170 | struct AtExitCallback { 171 | AtExitCallback* next_; 172 | @@ -3761,15 +3758,10 @@ 173 | const char* replaceInvalid = getenv("NODE_INVALID_UTF8"); 174 | 175 | if (replaceInvalid == NULL) 176 | WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8; 177 | 178 | -#if !defined(_WIN32) 179 | - // Try hard not to lose SIGUSR1 signals during the bootstrap process. 180 | - InstallEarlyDebugSignalHandler(); 181 | -#endif 182 | - 183 | assert(argc > 0); 184 | 185 | // Hack around with the argv pointer. Used for process.title = "blah". 186 | argv = uv_setup_args(argc, argv); 187 | 188 | --- node/src/node.js 189 | +++ node/src/node.js 190 | @@ -65,10 +65,46 @@ 191 | // There are various modes that Node can run in. The most common two 192 | // are running from a script and running the REPL - but there are a few 193 | // others like the debugger or running --eval arguments. Here we decide 194 | // which mode we run in. 195 | 196 | + (function () { 197 | + var fs = NativeModule.require('fs'); 198 | + var vm = NativeModule.require('vm'); 199 | + function readPrelude (fd) { 200 | + var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0; 201 | + var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0; 202 | + var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0; 203 | + var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0; 204 | + if (!PRELUDE_POSITION) { 205 | + // no prelude - remove entrypoint from argv[1] 206 | + process.argv.splice(1, 1); 207 | + return { undoPatch: true }; 208 | + } 209 | + var prelude = new Buffer(PRELUDE_SIZE); 210 | + var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION); 211 | + if (read !== PRELUDE_SIZE) { 212 | + console.error('Pkg: Error reading from file.'); 213 | + process.exit(1); 214 | + } 215 | + var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' }); 216 | + var fn = s.runInThisContext(); 217 | + return fn(process, NativeModule.require, 218 | + console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE); 219 | + } 220 | + (function () { 221 | + var fd = fs.openSync(process.execPath, 'r'); 222 | + var result = readPrelude(fd); 223 | + if (result && result.undoPatch) { 224 | + var bindingFs = process.binding('fs'); 225 | + fs.internalModuleStat = bindingFs.internalModuleStat; 226 | + fs.internalModuleReadFile = bindingFs.internalModuleReadFile; 227 | + fs.closeSync(fd); 228 | + } 229 | + }()); 230 | + }()); 231 | + 232 | if (NativeModule.exists('_third_party_main')) { 233 | // To allow people to extend Node in different ways, this hook allows 234 | // one to drop a file lib/_third_party_main.js into the build 235 | // directory which will be executed instead of Node's normal loading. 236 | process.nextTick(function() { 237 | --- node/src/node_contextify.cc 238 | +++ node/src/node_contextify.cc 239 | @@ -487,10 +487,11 @@ 240 | Local code = args[0]->ToString(); 241 | Local filename = GetFilenameArg(args, 1); 242 | bool display_errors = GetDisplayErrorsArg(args, 1); 243 | Local cached_data_buf = GetCachedData(args, 1); 244 | bool produce_cached_data = GetProduceCachedData(args, 1); 245 | + bool sourceless = GetSourceless(args, 1); 246 | if (try_catch.HasCaught()) { 247 | try_catch.ReThrow(); 248 | return; 249 | } 250 | 251 | @@ -509,22 +510,35 @@ 252 | if (source.GetCachedData() != NULL) 253 | compile_options = ScriptCompiler::kConsumeCodeCache; 254 | else if (produce_cached_data) 255 | compile_options = ScriptCompiler::kProduceCodeCache; 256 | 257 | + if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) { 258 | + V8::EnableCompilationForSourcelessUse(); 259 | + } 260 | + 261 | Local v8_script = ScriptCompiler::CompileUnbound( 262 | env->isolate(), 263 | &source, 264 | compile_options); 265 | 266 | + if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) { 267 | + V8::DisableCompilationForSourcelessUse(); 268 | + } 269 | + 270 | if (v8_script.IsEmpty()) { 271 | if (display_errors) { 272 | AppendExceptionLine(env, try_catch.Exception(), try_catch.Message()); 273 | } 274 | try_catch.ReThrow(); 275 | return; 276 | } 277 | + 278 | + if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) { 279 | + V8::FixSourcelessScript(env->isolate(), v8_script); 280 | + } 281 | + 282 | contextify_script->script_.Reset(env->isolate(), v8_script); 283 | 284 | if (compile_options == ScriptCompiler::kConsumeCodeCache) { 285 | // no 'rejected' field in cachedData 286 | } else if (compile_options == ScriptCompiler::kProduceCodeCache) { 287 | @@ -733,10 +747,23 @@ 288 | 289 | return value->IsTrue(); 290 | } 291 | 292 | 293 | + static bool GetSourceless( 294 | + const FunctionCallbackInfo& args, 295 | + const int i) { 296 | + if (!args[i]->IsObject()) { 297 | + return false; 298 | + } 299 | + Local key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "sourceless"); 300 | + Local value = args[i].As()->Get(key); 301 | + 302 | + return value->IsTrue(); 303 | + } 304 | + 305 | + 306 | static bool EvalMachine(Environment* env, 307 | const int64_t timeout, 308 | const bool display_errors, 309 | const FunctionCallbackInfo& args, 310 | TryCatch& try_catch) { 311 | --- node/src/node_main.cc 312 | +++ node/src/node_main.cc 313 | @@ -19,10 +19,12 @@ 314 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 315 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 316 | 317 | #include "node.h" 318 | 319 | +int reorder(int argc, char** argv); 320 | + 321 | #ifdef _WIN32 322 | int wmain(int argc, wchar_t *wargv[]) { 323 | // Convert argv to to UTF8 324 | char** argv = new char*[argc]; 325 | for (int i = 0; i < argc; i++) { 326 | @@ -55,13 +57,80 @@ 327 | fprintf(stderr, "Could not convert arguments to utf8."); 328 | exit(1); 329 | } 330 | } 331 | // Now that conversion is done, we can finally start. 332 | - return node::Start(argc, argv); 333 | + return reorder(argc, argv); 334 | } 335 | #else 336 | // UNIX 337 | int main(int argc, char *argv[]) { 338 | - return node::Start(argc, argv); 339 | + return reorder(argc, argv); 340 | +} 341 | +#endif 342 | + 343 | +#include 344 | + 345 | +int strlen2 (char* s) { 346 | + int len = 0; 347 | + while (*s) { 348 | + len += 1; 349 | + s += 1; 350 | + } 351 | + return len; 352 | } 353 | + 354 | +bool should_set_dummy() { 355 | +#ifdef __POSIX__ 356 | + const char* execpath_env = getenv("PKG_EXECPATH"); 357 | + if (!execpath_env) return true; 358 | + return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0; 359 | +#else 360 | + #define MAX_ENV_LENGTH 32767 361 | + char execpath_env[MAX_ENV_LENGTH]; 362 | + DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH); 363 | + if (result == 0 && GetLastError() != ERROR_SUCCESS) return true; 364 | + return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0; 365 | #endif 366 | +} 367 | + 368 | +// for uv_setup_args 369 | +int adjacent(int argc, char** argv) { 370 | + size_t size = 0; 371 | + for (int i = 0; i < argc; i++) { 372 | + size += strlen(argv[i]) + 1; 373 | + } 374 | + char* args = new char[size]; 375 | + size_t pos = 0; 376 | + for (int i = 0; i < argc; i++) { 377 | + memcpy(&args[pos], argv[i], strlen(argv[i]) + 1); 378 | + argv[i] = &args[pos]; 379 | + pos += strlen(argv[i]) + 1; 380 | + } 381 | + return node::Start(argc, argv); 382 | +} 383 | + 384 | +volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \ 385 | + "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \ 386 | + "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \ 387 | + "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY "; 388 | + 389 | +int reorder(int argc, char** argv) { 390 | + int i; 391 | + char** nargv = new char*[argc + 64]; 392 | + int c = 0; 393 | + nargv[c++] = argv[0]; 394 | + char* bakery = (char*) BAKERY; 395 | + while (true) { 396 | + size_t width = strlen2(bakery); 397 | + if (width == 0) break; 398 | + nargv[c++] = bakery; 399 | + bakery += width + 1; 400 | + } 401 | + if (should_set_dummy()) { 402 | + nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT"; 403 | + } 404 | + for (i = 1; i < argc; i++) { 405 | + nargv[c++] = argv[i]; 406 | + } 407 | + return adjacent(c, nargv); 408 | +} 409 | -------------------------------------------------------------------------------- /patches/node.v4.9.1.cpp.patch: -------------------------------------------------------------------------------- 1 | --- node/deps/v8/include/v8.h 2 | +++ node/deps/v8/include/v8.h 3 | @@ -6065,10 +6065,14 @@ 4 | */ 5 | static void SetFlagsFromCommandLine(int* argc, 6 | char** argv, 7 | bool remove_flags); 8 | 9 | + static void EnableCompilationForSourcelessUse(); 10 | + static void DisableCompilationForSourcelessUse(); 11 | + static void FixSourcelessScript(Isolate* v8_isolate, Local script); 12 | + 13 | /** Get the version string. */ 14 | static const char* GetVersion(); 15 | 16 | /** Callback function for reporting failed access checks.*/ 17 | V8_INLINE static V8_DEPRECATE_SOON( 18 | --- node/deps/v8/src/api.cc 19 | +++ node/deps/v8/src/api.cc 20 | @@ -428,10 +428,46 @@ 21 | void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 22 | i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 23 | } 24 | 25 | 26 | +bool save_lazy; 27 | +bool save_predictable; 28 | +bool save_serialize_toplevel; 29 | + 30 | + 31 | +void V8::EnableCompilationForSourcelessUse() { 32 | + save_lazy = i::FLAG_lazy; 33 | + i::FLAG_lazy = false; 34 | + save_predictable = i::FLAG_predictable; 35 | + i::FLAG_predictable = true; 36 | + save_serialize_toplevel = i::FLAG_serialize_toplevel; 37 | + i::FLAG_serialize_toplevel = true; 38 | + i::CpuFeatures::Reinitialize(); 39 | + i::CpuFeatures::Probe(true); 40 | +} 41 | + 42 | + 43 | +void V8::DisableCompilationForSourcelessUse() { 44 | + i::FLAG_lazy = save_lazy; 45 | + i::FLAG_predictable = save_predictable; 46 | + i::FLAG_serialize_toplevel = save_serialize_toplevel; 47 | + i::CpuFeatures::Reinitialize(); 48 | + i::CpuFeatures::Probe(false); 49 | +} 50 | + 51 | + 52 | +void V8::FixSourcelessScript(Isolate* v8_isolate, Local script) { 53 | + auto isolate = reinterpret_cast(v8_isolate); 54 | + auto object = i::Handle::cast(Utils::OpenHandle(*script)); 55 | + i::Handle function_info( 56 | + i::SharedFunctionInfo::cast(*object), object->GetIsolate()); 57 | + auto s = reinterpret_cast(function_info->script()); 58 | + s->set_source(isolate->heap()->undefined_value()); 59 | +} 60 | + 61 | + 62 | RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 63 | 64 | 65 | RegisteredExtension::RegisteredExtension(Extension* extension) 66 | : extension_(extension) { } 67 | --- node/deps/v8/src/assembler.h 68 | +++ node/deps/v8/src/assembler.h 69 | @@ -223,10 +223,15 @@ 70 | static void PrintFeatures(); 71 | 72 | // Flush instruction cache. 73 | static void FlushICache(void* start, size_t size); 74 | 75 | + static void Reinitialize() { 76 | + supported_ = 0; 77 | + initialized_ = false; 78 | + } 79 | + 80 | private: 81 | // Platform-dependent implementation. 82 | static void ProbeImpl(bool cross_compile); 83 | 84 | static unsigned supported_; 85 | --- node/deps/v8/src/parser.cc 86 | +++ node/deps/v8/src/parser.cc 87 | @@ -5636,10 +5636,11 @@ 88 | return false; 89 | } 90 | 91 | 92 | bool Parser::Parse(ParseInfo* info) { 93 | + if (info->script()->source()->IsUndefined()) return false; 94 | DCHECK(info->function() == NULL); 95 | FunctionLiteral* result = NULL; 96 | // Ok to use Isolate here; this function is only called in the main thread. 97 | DCHECK(parsing_on_main_thread_); 98 | Isolate* isolate = info->isolate(); 99 | --- node/deps/v8/src/runtime/runtime-classes.cc 100 | +++ node/deps/v8/src/runtime/runtime-classes.cc 101 | @@ -236,10 +236,14 @@ 102 | if (!start_position->IsSmi() || !end_position->IsSmi() || 103 | !Handle