mirror of
https://github.com/tiennm99/FBcount.git
synced 2026-09-08 02:18:27 +00:00
Init
This commit is contained in:
+65
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var _minimist = _interopRequireDefault(require("minimist"));
|
||||
|
||||
var _index2 = require("./index.js");
|
||||
|
||||
function main() {
|
||||
return _main.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _main() {
|
||||
_main = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee() {
|
||||
var argv, nodeRange, platform, arch, forceFetch, forceBuild, local;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
argv = (0, _minimist.default)(process.argv.slice(2), {
|
||||
boolean: ['f', 'b'],
|
||||
string: ['n', 'p', 'a']
|
||||
});
|
||||
nodeRange = argv.n || argv._.shift();
|
||||
platform = argv.p || argv._.shift();
|
||||
arch = argv.a || argv._.shift();
|
||||
forceFetch = argv.f;
|
||||
forceBuild = argv.b;
|
||||
_context.next = 8;
|
||||
return (0, _index2.need)({
|
||||
nodeRange,
|
||||
platform,
|
||||
arch,
|
||||
forceFetch,
|
||||
forceBuild
|
||||
});
|
||||
|
||||
case 8:
|
||||
local = _context.sent;
|
||||
|
||||
_log.log.info(local);
|
||||
|
||||
case 10:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee);
|
||||
}));
|
||||
return _main.apply(this, arguments);
|
||||
}
|
||||
|
||||
main().catch(function (error) {
|
||||
if (!error.wasReported) _log.log.error(error);
|
||||
process.exit(2);
|
||||
});
|
||||
+418
@@ -0,0 +1,418 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = build;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _fsExtra = require("fs-extra");
|
||||
|
||||
var _spawn = require("./spawn.js");
|
||||
|
||||
var _copyFile = require("./copy-file.js");
|
||||
|
||||
var _system = require("./system.js");
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var _patches = _interopRequireDefault(require("../patches/patches.json"));
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
var _tempPath = require("./temp-path.js");
|
||||
|
||||
var _thresholds = _interopRequireDefault(require("./thresholds.js"));
|
||||
|
||||
var buildPath;
|
||||
|
||||
if (process.env.GITHUB_USERNAME) {
|
||||
buildPath = _path.default.join(__dirname, '..', 'precompile');
|
||||
} else {
|
||||
buildPath = (0, _tempPath.tempPath)();
|
||||
}
|
||||
|
||||
var nodePath = _path.default.join(buildPath, 'node');
|
||||
|
||||
var patchesPath = _path.default.resolve(__dirname, '../patches');
|
||||
|
||||
var nodeRepo = 'https://github.com/nodejs/node';
|
||||
|
||||
function gitClone() {
|
||||
return _gitClone.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _gitClone() {
|
||||
_gitClone = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee() {
|
||||
var args, promise;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_log.log.info('Cloning Node.js repository from GitHub...');
|
||||
|
||||
args = ['clone', '--bare', '--progress', nodeRepo, 'node/.git'];
|
||||
promise = (0, _spawn.spawn)('git', args, {
|
||||
cwd: buildPath
|
||||
});
|
||||
(0, _spawn.progress)(promise, (0, _thresholds.default)('clone'));
|
||||
_context.next = 6;
|
||||
return promise;
|
||||
|
||||
case 6:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee);
|
||||
}));
|
||||
return _gitClone.apply(this, arguments);
|
||||
}
|
||||
|
||||
function gitResetHard(_x) {
|
||||
return _gitResetHard.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _gitResetHard() {
|
||||
_gitResetHard = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee2(nodeVersion) {
|
||||
var patches, commit, args;
|
||||
return _index.default.wrap(function _callee2$(_context2) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
case 0:
|
||||
_log.log.info(`Checking out ${nodeVersion}`);
|
||||
|
||||
patches = _patches.default[nodeVersion];
|
||||
commit = patches.commit || nodeVersion;
|
||||
args = ['--work-tree', '.', 'reset', '--hard', commit];
|
||||
_context2.next = 6;
|
||||
return (0, _spawn.spawn)('git', args, {
|
||||
cwd: nodePath
|
||||
});
|
||||
|
||||
case 6:
|
||||
case "end":
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2);
|
||||
}));
|
||||
return _gitResetHard.apply(this, arguments);
|
||||
}
|
||||
|
||||
function applyPatches(_x2) {
|
||||
return _applyPatches.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _applyPatches() {
|
||||
_applyPatches = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee3(nodeVersion) {
|
||||
var patches, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, patch, patchPath, args;
|
||||
|
||||
return _index.default.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
_log.log.info('Applying patches');
|
||||
|
||||
patches = _patches.default[nodeVersion];
|
||||
patches = patches.patches || patches;
|
||||
if (patches.sameAs) patches = _patches.default[patches.sameAs];
|
||||
_iteratorNormalCompletion = true;
|
||||
_didIteratorError = false;
|
||||
_iteratorError = undefined;
|
||||
_context3.prev = 7;
|
||||
_iterator = patches[Symbol.iterator]();
|
||||
|
||||
case 9:
|
||||
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
|
||||
_context3.next = 18;
|
||||
break;
|
||||
}
|
||||
|
||||
patch = _step.value;
|
||||
patchPath = _path.default.join(patchesPath, patch);
|
||||
args = ['-p1', '-i', patchPath];
|
||||
_context3.next = 15;
|
||||
return (0, _spawn.spawn)('patch', args, {
|
||||
cwd: nodePath
|
||||
});
|
||||
|
||||
case 15:
|
||||
_iteratorNormalCompletion = true;
|
||||
_context3.next = 9;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
_context3.next = 24;
|
||||
break;
|
||||
|
||||
case 20:
|
||||
_context3.prev = 20;
|
||||
_context3.t0 = _context3["catch"](7);
|
||||
_didIteratorError = true;
|
||||
_iteratorError = _context3.t0;
|
||||
|
||||
case 24:
|
||||
_context3.prev = 24;
|
||||
_context3.prev = 25;
|
||||
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
|
||||
case 27:
|
||||
_context3.prev = 27;
|
||||
|
||||
if (!_didIteratorError) {
|
||||
_context3.next = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
throw _iteratorError;
|
||||
|
||||
case 30:
|
||||
return _context3.finish(27);
|
||||
|
||||
case 31:
|
||||
return _context3.finish(24);
|
||||
|
||||
case 32:
|
||||
case "end":
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee3, null, [[7, 20, 24, 32], [25,, 27, 31]]);
|
||||
}));
|
||||
return _applyPatches.apply(this, arguments);
|
||||
}
|
||||
|
||||
function compileOnWindows(_x3, _x4) {
|
||||
return _compileOnWindows.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _compileOnWindows() {
|
||||
_compileOnWindows = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee4(nodeVersion, targetArch) {
|
||||
var args, major, promise;
|
||||
return _index.default.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
args = [];
|
||||
args.push('/c', 'vcbuild.bat', targetArch, 'noetw');
|
||||
major = nodeVersion.match(/^v?(\d+)/)[1] | 0;
|
||||
if (major <= 10) args.push('nosign', 'noperfctr');
|
||||
promise = (0, _spawn.spawn)('cmd', args, {
|
||||
cwd: nodePath
|
||||
});
|
||||
(0, _spawn.progress)(promise, (0, _thresholds.default)('vcbuild', nodeVersion));
|
||||
_context4.next = 8;
|
||||
return promise;
|
||||
|
||||
case 8:
|
||||
if (!(major <= 10)) {
|
||||
_context4.next = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context4.abrupt("return", _path.default.join(nodePath, 'Release/node.exe'));
|
||||
|
||||
case 10:
|
||||
return _context4.abrupt("return", _path.default.join(nodePath, 'out/Release/node.exe'));
|
||||
|
||||
case 11:
|
||||
case "end":
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4);
|
||||
}));
|
||||
return _compileOnWindows.apply(this, arguments);
|
||||
}
|
||||
|
||||
function compileOnUnix(_x5, _x6) {
|
||||
return _compileOnUnix.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _compileOnUnix() {
|
||||
_compileOnUnix = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee5(nodeVersion, targetArch) {
|
||||
var args, cpu, major, make, promise, output;
|
||||
return _index.default.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
args = [];
|
||||
cpu = {
|
||||
x86: 'ia32',
|
||||
x64: 'x64',
|
||||
armv6: 'arm',
|
||||
armv7: 'arm',
|
||||
arm64: 'arm64',
|
||||
s390x: 's390x'
|
||||
}[targetArch];
|
||||
args.push('--dest-cpu', cpu); // first of all v8_inspector introduces the use
|
||||
// of `prime_rehash_policy` symbol that requires
|
||||
// GLIBCXX_3.4.18 on some systems
|
||||
// also we don't support any kind of debugging
|
||||
// against packaged apps, hence v8_inspector is useless
|
||||
|
||||
major = nodeVersion.match(/^v?(\d+)/)[1] | 0;
|
||||
if (major >= 6) args.push('--without-inspector'); // https://github.com/mhart/alpine-node/blob/base-7.4.0/Dockerfile#L33
|
||||
|
||||
if (_system.hostPlatform === 'alpine') args.push('--without-snapshot'); // TODO same for windows?
|
||||
|
||||
_context5.next = 8;
|
||||
return (0, _spawn.spawn)('./configure', args, {
|
||||
cwd: nodePath
|
||||
});
|
||||
|
||||
case 8:
|
||||
make = _system.hostPlatform === 'freebsd' ? 'gmake' : 'make';
|
||||
promise = (0, _spawn.spawn)(make, [], {
|
||||
cwd: nodePath
|
||||
});
|
||||
(0, _spawn.progress)(promise, (0, _thresholds.default)('make', nodeVersion));
|
||||
_context5.next = 13;
|
||||
return promise;
|
||||
|
||||
case 13:
|
||||
output = _path.default.join(nodePath, 'out/Release/node'); // https://github.com/mhart/alpine-node/blob/base-7.4.0/Dockerfile#L36
|
||||
|
||||
if (!(_system.hostPlatform === 'alpine')) {
|
||||
_context5.next = 17;
|
||||
break;
|
||||
}
|
||||
|
||||
_context5.next = 17;
|
||||
return (0, _spawn.spawn)('paxctl', ['-cm', output]);
|
||||
|
||||
case 17:
|
||||
return _context5.abrupt("return", output);
|
||||
|
||||
case 18:
|
||||
case "end":
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5);
|
||||
}));
|
||||
return _compileOnUnix.apply(this, arguments);
|
||||
}
|
||||
|
||||
function compile(_x7, _x8) {
|
||||
return _compile.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _compile() {
|
||||
_compile = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee6(nodeVersion, targetArch) {
|
||||
var win;
|
||||
return _index.default.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
_log.log.info('Compiling Node.js from sources...');
|
||||
|
||||
win = _system.hostPlatform === 'win';
|
||||
|
||||
if (!win) {
|
||||
_context6.next = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
_context6.next = 5;
|
||||
return compileOnWindows(nodeVersion, targetArch);
|
||||
|
||||
case 5:
|
||||
return _context6.abrupt("return", _context6.sent);
|
||||
|
||||
case 6:
|
||||
_context6.next = 8;
|
||||
return compileOnUnix(nodeVersion, targetArch);
|
||||
|
||||
case 8:
|
||||
return _context6.abrupt("return", _context6.sent);
|
||||
|
||||
case 9:
|
||||
case "end":
|
||||
return _context6.stop();
|
||||
}
|
||||
}
|
||||
}, _callee6);
|
||||
}));
|
||||
return _compile.apply(this, arguments);
|
||||
}
|
||||
|
||||
function build(_x9, _x10, _x11) {
|
||||
return _build.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _build() {
|
||||
_build = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee7(nodeVersion, targetArch, local) {
|
||||
var output;
|
||||
return _index.default.wrap(function _callee7$(_context7) {
|
||||
while (1) {
|
||||
switch (_context7.prev = _context7.next) {
|
||||
case 0:
|
||||
_context7.next = 2;
|
||||
return (0, _fsExtra.remove)(buildPath);
|
||||
|
||||
case 2:
|
||||
_context7.next = 4;
|
||||
return (0, _fsExtra.mkdirp)(buildPath);
|
||||
|
||||
case 4:
|
||||
_context7.next = 6;
|
||||
return gitClone();
|
||||
|
||||
case 6:
|
||||
_context7.next = 8;
|
||||
return gitResetHard(nodeVersion);
|
||||
|
||||
case 8:
|
||||
_context7.next = 10;
|
||||
return applyPatches(nodeVersion);
|
||||
|
||||
case 10:
|
||||
_context7.next = 12;
|
||||
return compile(nodeVersion, targetArch);
|
||||
|
||||
case 12:
|
||||
output = _context7.sent;
|
||||
_context7.next = 15;
|
||||
return (0, _fsExtra.mkdirp)(_path.default.dirname(local));
|
||||
|
||||
case 15:
|
||||
_context7.next = 17;
|
||||
return (0, _copyFile.copyFile)(output, local);
|
||||
|
||||
case 17:
|
||||
_context7.next = 19;
|
||||
return (0, _fsExtra.remove)(buildPath);
|
||||
|
||||
case 19:
|
||||
case "end":
|
||||
return _context7.stop();
|
||||
}
|
||||
}
|
||||
}, _callee7);
|
||||
}));
|
||||
return _build.apply(this, arguments);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.plusx = plusx;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _fsExtra = require("fs-extra");
|
||||
|
||||
function plusx(_x) {
|
||||
return _plusx.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _plusx() {
|
||||
_plusx = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee(file) {
|
||||
var s, newMode, base8;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.next = 2;
|
||||
return (0, _fsExtra.stat)(file);
|
||||
|
||||
case 2:
|
||||
s = _context.sent;
|
||||
newMode = s.mode | 64 | 8 | 1;
|
||||
|
||||
if (!(s.mode === newMode)) {
|
||||
_context.next = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return");
|
||||
|
||||
case 6:
|
||||
base8 = newMode.toString(8).slice(-3);
|
||||
_context.next = 9;
|
||||
return (0, _fsExtra.chmod)(file, base8);
|
||||
|
||||
case 9:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee);
|
||||
}));
|
||||
return _plusx.apply(this, arguments);
|
||||
}
|
||||
+456
@@ -0,0 +1,456 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Cloud = void 0;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck.js"));
|
||||
|
||||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass.js"));
|
||||
|
||||
var _fsExtra = require("fs-extra");
|
||||
|
||||
var _github = require("./github.js");
|
||||
|
||||
var _assert = _interopRequireDefault(require("assert"));
|
||||
|
||||
var _copyFile = require("./copy-file.js");
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
function uniqueName(name, names) {
|
||||
if (names.indexOf(name) < 0) return name;
|
||||
var newName;
|
||||
var counter = 0;
|
||||
|
||||
while (true) {
|
||||
newName = `${name}-new-${counter}`;
|
||||
if (names.indexOf(newName) < 0) return newName;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var Cloud =
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
function Cloud(_ref) {
|
||||
var owner = _ref.owner,
|
||||
repo = _ref.repo;
|
||||
(0, _classCallCheck2.default)(this, Cloud);
|
||||
this.gh = new _github.GitHub({
|
||||
owner,
|
||||
repo
|
||||
});
|
||||
}
|
||||
|
||||
(0, _createClass2.default)(Cloud, [{
|
||||
key: "_findRelease",
|
||||
value: function () {
|
||||
var _findRelease2 = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee(tag) {
|
||||
var release;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.next = 2;
|
||||
return this.gh.getRelease(tag);
|
||||
|
||||
case 2:
|
||||
release = _context.sent;
|
||||
|
||||
if (release) {
|
||||
_context.next = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 6;
|
||||
return this.gh.getReleaseDraft(tag);
|
||||
|
||||
case 6:
|
||||
release = _context.sent;
|
||||
|
||||
case 7:
|
||||
if (release) {
|
||||
_context.next = 11;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 10;
|
||||
return this.gh.createRelease(tag);
|
||||
|
||||
case 10:
|
||||
release = _context.sent;
|
||||
|
||||
case 11:
|
||||
return _context.abrupt("return", release);
|
||||
|
||||
case 12:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this);
|
||||
}));
|
||||
|
||||
function _findRelease(_x) {
|
||||
return _findRelease2.apply(this, arguments);
|
||||
}
|
||||
|
||||
return _findRelease;
|
||||
}()
|
||||
}, {
|
||||
key: "alreadyUploaded",
|
||||
value: function () {
|
||||
var _alreadyUploaded = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee2(remote) {
|
||||
var release;
|
||||
return _index.default.wrap(function _callee2$(_context2) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
case 0:
|
||||
_context2.next = 2;
|
||||
return this._findRelease(remote.tag);
|
||||
|
||||
case 2:
|
||||
release = _context2.sent;
|
||||
return _context2.abrupt("return", release.assets.some(function (_ref2) {
|
||||
var name = _ref2.name;
|
||||
(0, _assert.default)(name);
|
||||
return remote.name === name;
|
||||
}));
|
||||
|
||||
case 4:
|
||||
case "end":
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, this);
|
||||
}));
|
||||
|
||||
function alreadyUploaded(_x2) {
|
||||
return _alreadyUploaded.apply(this, arguments);
|
||||
}
|
||||
|
||||
return alreadyUploaded;
|
||||
}()
|
||||
}, {
|
||||
key: "upload",
|
||||
value: function () {
|
||||
var _upload = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee3(local, remote) {
|
||||
var release, names, name;
|
||||
return _index.default.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
_context3.next = 2;
|
||||
return this._findRelease(remote.tag);
|
||||
|
||||
case 2:
|
||||
release = _context3.sent;
|
||||
names = release.assets.map(function (_ref3) {
|
||||
var name = _ref3.name;
|
||||
(0, _assert.default)(name);
|
||||
return name;
|
||||
});
|
||||
name = uniqueName(remote.name, names);
|
||||
_context3.next = 7;
|
||||
return this.gh.uploadAsset(local, release, name);
|
||||
|
||||
case 7:
|
||||
case "end":
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee3, this);
|
||||
}));
|
||||
|
||||
function upload(_x3, _x4) {
|
||||
return _upload.apply(this, arguments);
|
||||
}
|
||||
|
||||
return upload;
|
||||
}()
|
||||
}, {
|
||||
key: "uploadMany",
|
||||
value: function () {
|
||||
var _uploadMany = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee4(items) {
|
||||
var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, item, local, remote;
|
||||
|
||||
return _index.default.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
_iteratorNormalCompletion = true;
|
||||
_didIteratorError = false;
|
||||
_iteratorError = undefined;
|
||||
_context4.prev = 3;
|
||||
_iterator = items[Symbol.iterator]();
|
||||
|
||||
case 5:
|
||||
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
|
||||
_context4.next = 13;
|
||||
break;
|
||||
}
|
||||
|
||||
item = _step.value;
|
||||
local = item.local, remote = item.remote;
|
||||
_context4.next = 10;
|
||||
return this.upload(local, remote);
|
||||
|
||||
case 10:
|
||||
_iteratorNormalCompletion = true;
|
||||
_context4.next = 5;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
_context4.next = 19;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
_context4.prev = 15;
|
||||
_context4.t0 = _context4["catch"](3);
|
||||
_didIteratorError = true;
|
||||
_iteratorError = _context4.t0;
|
||||
|
||||
case 19:
|
||||
_context4.prev = 19;
|
||||
_context4.prev = 20;
|
||||
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
|
||||
case 22:
|
||||
_context4.prev = 22;
|
||||
|
||||
if (!_didIteratorError) {
|
||||
_context4.next = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
throw _iteratorError;
|
||||
|
||||
case 25:
|
||||
return _context4.finish(22);
|
||||
|
||||
case 26:
|
||||
return _context4.finish(19);
|
||||
|
||||
case 27:
|
||||
case "end":
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this, [[3, 15, 19, 27], [20,, 22, 26]]);
|
||||
}));
|
||||
|
||||
function uploadMany(_x5) {
|
||||
return _uploadMany.apply(this, arguments);
|
||||
}
|
||||
|
||||
return uploadMany;
|
||||
}()
|
||||
}, {
|
||||
key: "download",
|
||||
value: function () {
|
||||
var _download = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee5(remote, local) {
|
||||
var tag, tempFile, short, ok, release, assets, asset;
|
||||
return _index.default.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
tag = remote.tag;
|
||||
tempFile = local + '.downloading';
|
||||
_context5.next = 4;
|
||||
return (0, _fsExtra.mkdirp)(_path.default.dirname(tempFile));
|
||||
|
||||
case 4:
|
||||
short = _path.default.basename(local);
|
||||
_context5.next = 7;
|
||||
return this.gh.tryDirectly(tag, remote.name, tempFile, short);
|
||||
|
||||
case 7:
|
||||
ok = _context5.sent;
|
||||
|
||||
if (ok) {
|
||||
_context5.next = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
_context5.next = 11;
|
||||
return this.gh.getRelease(tag);
|
||||
|
||||
case 11:
|
||||
release = _context5.sent;
|
||||
|
||||
if (release) {
|
||||
_context5.next = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
_context5.next = 15;
|
||||
return this.gh.getReleaseDraft(tag);
|
||||
|
||||
case 15:
|
||||
release = _context5.sent;
|
||||
|
||||
case 16:
|
||||
if (release) {
|
||||
_context5.next = 18;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context5.abrupt("return", false);
|
||||
|
||||
case 18:
|
||||
assets = release.assets.filter(function (_ref4) {
|
||||
var name = _ref4.name;
|
||||
(0, _assert.default)(name);
|
||||
return name === remote.name;
|
||||
});
|
||||
|
||||
if (assets.length) {
|
||||
_context5.next = 21;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context5.abrupt("return", false);
|
||||
|
||||
case 21:
|
||||
(0, _assert.default)(assets.length === 1);
|
||||
asset = assets[0];
|
||||
_context5.next = 25;
|
||||
return this.gh.downloadUrl(asset.url, tempFile, short);
|
||||
|
||||
case 25:
|
||||
_context5.next = 27;
|
||||
return (0, _fsExtra.remove)(local);
|
||||
|
||||
case 27:
|
||||
_context5.next = 29;
|
||||
return (0, _copyFile.moveFile)(tempFile, local);
|
||||
|
||||
case 29:
|
||||
_context5.next = 31;
|
||||
return (0, _fsExtra.remove)(tempFile);
|
||||
|
||||
case 31:
|
||||
return _context5.abrupt("return", true);
|
||||
|
||||
case 32:
|
||||
case "end":
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5, this);
|
||||
}));
|
||||
|
||||
function download(_x6, _x7) {
|
||||
return _download.apply(this, arguments);
|
||||
}
|
||||
|
||||
return download;
|
||||
}()
|
||||
}, {
|
||||
key: "downloadMany",
|
||||
value: function () {
|
||||
var _downloadMany = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee6(items) {
|
||||
var _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, item, remote, local;
|
||||
|
||||
return _index.default.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
_iteratorNormalCompletion2 = true;
|
||||
_didIteratorError2 = false;
|
||||
_iteratorError2 = undefined;
|
||||
_context6.prev = 3;
|
||||
_iterator2 = items[Symbol.iterator]();
|
||||
|
||||
case 5:
|
||||
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
|
||||
_context6.next = 13;
|
||||
break;
|
||||
}
|
||||
|
||||
item = _step2.value;
|
||||
remote = item.remote, local = item.local;
|
||||
_context6.next = 10;
|
||||
return this.download(remote, local);
|
||||
|
||||
case 10:
|
||||
_iteratorNormalCompletion2 = true;
|
||||
_context6.next = 5;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
_context6.next = 19;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
_context6.prev = 15;
|
||||
_context6.t0 = _context6["catch"](3);
|
||||
_didIteratorError2 = true;
|
||||
_iteratorError2 = _context6.t0;
|
||||
|
||||
case 19:
|
||||
_context6.prev = 19;
|
||||
_context6.prev = 20;
|
||||
|
||||
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
||||
_iterator2.return();
|
||||
}
|
||||
|
||||
case 22:
|
||||
_context6.prev = 22;
|
||||
|
||||
if (!_didIteratorError2) {
|
||||
_context6.next = 25;
|
||||
break;
|
||||
}
|
||||
|
||||
throw _iteratorError2;
|
||||
|
||||
case 25:
|
||||
return _context6.finish(22);
|
||||
|
||||
case 26:
|
||||
return _context6.finish(19);
|
||||
|
||||
case 27:
|
||||
case "end":
|
||||
return _context6.stop();
|
||||
}
|
||||
}
|
||||
}, _callee6, this, [[3, 15, 19, 27], [20,, 22, 26]]);
|
||||
}));
|
||||
|
||||
function downloadMany(_x8) {
|
||||
return _downloadMany.apply(this, arguments);
|
||||
}
|
||||
|
||||
return downloadMany;
|
||||
}()
|
||||
}]);
|
||||
return Cloud;
|
||||
}();
|
||||
|
||||
exports.Cloud = Cloud;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.copyFile = copyFile;
|
||||
exports.moveFile = moveFile;
|
||||
|
||||
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
||||
|
||||
function copyFile(src, dest) {
|
||||
return _fsExtra.default.copy(src, dest);
|
||||
}
|
||||
|
||||
function moveFile(src, dest) {
|
||||
return _fsExtra.default.move(src, dest);
|
||||
}
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.GitHub = void 0;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck.js"));
|
||||
|
||||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass.js"));
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var _assert = _interopRequireDefault(require("assert"));
|
||||
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
|
||||
var _requestProgress = _interopRequireDefault(require("request-progress"));
|
||||
|
||||
var _request = _interopRequireDefault(require("request"));
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
var GitHub =
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
function GitHub(_ref) {
|
||||
var owner = _ref.owner,
|
||||
repo = _ref.repo;
|
||||
(0, _classCallCheck2.default)(this, GitHub);
|
||||
this.owner = owner;
|
||||
this.repo = repo;
|
||||
var _process$env = process.env,
|
||||
GITHUB_USERNAME = _process$env.GITHUB_USERNAME,
|
||||
GITHUB_PASSWORD = _process$env.GITHUB_PASSWORD;
|
||||
var auth = {
|
||||
user: GITHUB_USERNAME,
|
||||
pass: GITHUB_PASSWORD
|
||||
};
|
||||
this.request = _request.default.defaults({
|
||||
auth: auth.user ? auth : undefined,
|
||||
headers: {
|
||||
'User-Agent': `${this.owner}/${this.repo}/${GITHUB_USERNAME}`
|
||||
},
|
||||
timeout: 30 * 1000
|
||||
});
|
||||
}
|
||||
|
||||
(0, _createClass2.default)(GitHub, [{
|
||||
key: "getRelease",
|
||||
value: function getRelease(tag) {
|
||||
var _this = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var url = `https://api.github.com/repos/${_this.owner}/${_this.repo}/releases/tags/${tag}`;
|
||||
|
||||
_this.request(url, function (error, response, body) {
|
||||
if (error) return reject((0, _log.wasReported)(error.message));
|
||||
var release = JSON.parse(body);
|
||||
var message = release.message;
|
||||
if (message === 'Not Found') return resolve(undefined);
|
||||
if (message) return reject((0, _log.wasReported)(message));
|
||||
resolve(release);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "getReleaseDraft",
|
||||
value: function getReleaseDraft(tag) {
|
||||
var _this2 = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var url = `https://api.github.com/repos/${_this2.owner}/${_this2.repo}/releases`;
|
||||
|
||||
_this2.request(url, function (error, response, body) {
|
||||
if (error) return reject((0, _log.wasReported)(error.message)); // here we use `get release by tag` endpoint
|
||||
// because draft releases are really `untagged`.
|
||||
// seems that `get release by tag` is for non-drafts.
|
||||
// hence listing all releases and looking through them
|
||||
|
||||
var releases = JSON.parse(body);
|
||||
if (releases.message) return reject((0, _log.wasReported)(releases.message));
|
||||
var found = releases.filter(function (_ref2) {
|
||||
var tag_name = _ref2.tag_name;
|
||||
return tag_name === tag;
|
||||
}); // eslint-disable-line camelcase
|
||||
|
||||
(0, _assert.default)(found.length <= 1);
|
||||
if (!found.length) return resolve(undefined);
|
||||
resolve(found[0]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "createRelease",
|
||||
value: function createRelease(tag) {
|
||||
var _this3 = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var form = JSON.stringify({
|
||||
tag_name: tag,
|
||||
target_commitish: 'master',
|
||||
// TODO maybe git rev-parse HEAD
|
||||
name: tag,
|
||||
draft: true,
|
||||
prerelease: true
|
||||
});
|
||||
var url = `https://api.github.com/repos/${_this3.owner}/${_this3.repo}/releases`;
|
||||
|
||||
_this3.request.post(url, {
|
||||
form
|
||||
}, function (error, response, body) {
|
||||
if (error) return reject((0, _log.wasReported)(error.message));
|
||||
var release = JSON.parse(body);
|
||||
if (release.message) return reject((0, _log.wasReported)(release.message));
|
||||
resolve(release);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "uploadAsset",
|
||||
value: function uploadAsset(file, release, name) {
|
||||
var _this4 = this;
|
||||
|
||||
(0, _assert.default)(!/[\\/]/.test(name));
|
||||
return new Promise(function (resolve, reject) {
|
||||
_fs.default.stat(file, function (error, stat) {
|
||||
if (error) return reject(error);
|
||||
var headers = {
|
||||
'Content-Length': stat.size,
|
||||
'Content-Type': 'application/octet-stream'
|
||||
};
|
||||
|
||||
var rs = _fs.default.createReadStream(file);
|
||||
|
||||
var subst = `?name=${name}`;
|
||||
var url = release.upload_url.replace(/\{\?name,label\}/, subst);
|
||||
|
||||
var req = _this4.request.post(url, {
|
||||
headers,
|
||||
timeout: 30 * 60 * 1000
|
||||
}, function (error2, response, body) {
|
||||
if (error2) return reject((0, _log.wasReported)(error2.message));
|
||||
var asset = JSON.parse(body);
|
||||
var errors = asset.errors;
|
||||
if (errors && errors[0]) return reject((0, _log.wasReported)(errors[0].code));
|
||||
if (asset.message) return reject((0, _log.wasReported)(asset.message));
|
||||
resolve(asset);
|
||||
});
|
||||
|
||||
rs.pipe(req);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "downloadUrl",
|
||||
value: function downloadUrl(url, file, short) {
|
||||
var _this5 = this;
|
||||
|
||||
_log.log.enableProgress(short);
|
||||
|
||||
_log.log.showProgress(0);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var headers = {
|
||||
Accept: 'application/octet-stream'
|
||||
};
|
||||
|
||||
var ws = _fs.default.createWriteStream(file);
|
||||
|
||||
var result;
|
||||
var req = (0, _requestProgress.default)(_this5.request.get(url, {
|
||||
headers
|
||||
}, function (error, response) {
|
||||
if (error) {
|
||||
_log.log.disableProgress();
|
||||
|
||||
return reject((0, _log.wasReported)(error.message));
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
_log.log.disableProgress();
|
||||
|
||||
var message = `${response.statusCode} ${response.body}`;
|
||||
return reject((0, _log.wasReported)(message, url));
|
||||
}
|
||||
|
||||
result = response;
|
||||
}));
|
||||
req.on('progress', function (state) {
|
||||
var p;
|
||||
|
||||
if (state.size && state.size.transferred && state.size.total) {
|
||||
p = state.size.transferred / state.size.total;
|
||||
} else {
|
||||
p = state.percentage;
|
||||
}
|
||||
|
||||
_log.log.showProgress(p * 100);
|
||||
});
|
||||
req.pipe(ws);
|
||||
ws.on('close', function () {
|
||||
_log.log.showProgress(100);
|
||||
|
||||
_log.log.disableProgress();
|
||||
|
||||
resolve(result);
|
||||
}).on('error', function (error) {
|
||||
_log.log.disableProgress();
|
||||
|
||||
reject((0, _log.wasReported)(error.message));
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "tryDirectly",
|
||||
value: function () {
|
||||
var _tryDirectly = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee(tag, name, file, short) {
|
||||
var url;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.prev = 0;
|
||||
url = `https://github.com/${this.owner}/${this.repo}/releases/download/${tag}/${name}`;
|
||||
_context.next = 4;
|
||||
return this.downloadUrl(url, file, short);
|
||||
|
||||
case 4:
|
||||
return _context.abrupt("return", true);
|
||||
|
||||
case 7:
|
||||
_context.prev = 7;
|
||||
_context.t0 = _context["catch"](0);
|
||||
|
||||
_log.log.info('Asset not found by direct link:', JSON.stringify({
|
||||
tag,
|
||||
name
|
||||
}));
|
||||
|
||||
return _context.abrupt("return", false);
|
||||
|
||||
case 11:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this, [[0, 7]]);
|
||||
}));
|
||||
|
||||
function tryDirectly(_x, _x2, _x3, _x4) {
|
||||
return _tryDirectly.apply(this, arguments);
|
||||
}
|
||||
|
||||
return tryDirectly;
|
||||
}()
|
||||
}]);
|
||||
return GitHub;
|
||||
}();
|
||||
|
||||
exports.GitHub = GitHub;
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard.js");
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.need = need;
|
||||
exports.system = void 0;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var system = _interopRequireWildcard(require("./system.js"));
|
||||
|
||||
exports.system = system;
|
||||
|
||||
var _places = require("./places.js");
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var _cloud = require("./cloud.js");
|
||||
|
||||
var _build = _interopRequireDefault(require("./build.js"));
|
||||
|
||||
var _fsExtra = require("fs-extra");
|
||||
|
||||
var _patches = _interopRequireDefault(require("../patches/patches.json"));
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
var _semver = _interopRequireDefault(require("semver"));
|
||||
|
||||
var _package = require("../package.json");
|
||||
|
||||
var cloud = new _cloud.Cloud({
|
||||
owner: 'zeit',
|
||||
repo: 'pkg-fetch'
|
||||
});
|
||||
|
||||
function need() {
|
||||
return _need.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _need() {
|
||||
_need = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee() {
|
||||
var opts,
|
||||
nodeRange,
|
||||
platform,
|
||||
arch,
|
||||
forceFetch,
|
||||
forceBuild,
|
||||
dryRun,
|
||||
satisfyingNodeVersion,
|
||||
nodeVersion,
|
||||
fetched,
|
||||
built,
|
||||
remote,
|
||||
fetchFailed,
|
||||
_args = arguments;
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
satisfyingNodeVersion = function _ref() {
|
||||
var versions = Object.keys(_patches.default).filter(function (nv) {
|
||||
return _semver.default.satisfies(nv, nodeRange) || nodeRange === 'latest';
|
||||
}).sort(function (nv1, nv2) {
|
||||
return _semver.default.gt(nv1, nv2) ? 1 : -1;
|
||||
});
|
||||
return versions.pop();
|
||||
};
|
||||
|
||||
opts = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
|
||||
// eslint-disable-line complexity
|
||||
nodeRange = opts.nodeRange, platform = opts.platform, arch = opts.arch, forceFetch = opts.forceFetch, forceBuild = opts.forceBuild, dryRun = opts.dryRun;
|
||||
|
||||
if (nodeRange) {
|
||||
_context.next = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)('nodeRange not specified');
|
||||
|
||||
case 5:
|
||||
if (platform) {
|
||||
_context.next = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)('platform not specified');
|
||||
|
||||
case 7:
|
||||
if (arch) {
|
||||
_context.next = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)('arch not specified');
|
||||
|
||||
case 9:
|
||||
nodeRange = (0, system.abiToNodeRange)(nodeRange); // 'm48' -> 'node6'
|
||||
|
||||
if ((0, system.isValidNodeRange)(nodeRange)) {
|
||||
_context.next = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)('nodeRange must start with \'node\'');
|
||||
|
||||
case 12:
|
||||
if (nodeRange !== 'latest') {
|
||||
nodeRange = 'v' + nodeRange.slice(4); // 'node6' -> 'v6' for semver
|
||||
}
|
||||
|
||||
platform = (0, system.toFancyPlatform)(platform); // win32 -> win
|
||||
|
||||
arch = (0, system.toFancyArch)(arch); // ia32 -> x86
|
||||
|
||||
nodeVersion = satisfyingNodeVersion();
|
||||
|
||||
if (nodeVersion) {
|
||||
_context.next = 18;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)(`No available node version satisfies '${opts.nodeRange}'`);
|
||||
|
||||
case 18:
|
||||
fetched = (0, _places.localPlace)({
|
||||
from: 'fetched',
|
||||
arch,
|
||||
nodeVersion,
|
||||
platform,
|
||||
version: _package.version
|
||||
});
|
||||
built = (0, _places.localPlace)({
|
||||
from: 'built',
|
||||
arch,
|
||||
nodeVersion,
|
||||
platform,
|
||||
version: _package.version
|
||||
});
|
||||
remote = (0, _places.remotePlace)({
|
||||
arch,
|
||||
nodeVersion,
|
||||
platform,
|
||||
version: _package.version
|
||||
});
|
||||
|
||||
if (forceBuild) {
|
||||
_context.next = 28;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 24;
|
||||
return (0, _fsExtra.exists)(fetched);
|
||||
|
||||
case 24:
|
||||
if (!_context.sent) {
|
||||
_context.next = 28;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
_context.next = 27;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return", 'exists');
|
||||
|
||||
case 27:
|
||||
return _context.abrupt("return", fetched);
|
||||
|
||||
case 28:
|
||||
if (forceFetch) {
|
||||
_context.next = 36;
|
||||
break;
|
||||
}
|
||||
|
||||
_context.next = 31;
|
||||
return (0, _fsExtra.exists)(built);
|
||||
|
||||
case 31:
|
||||
if (!_context.sent) {
|
||||
_context.next = 36;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
_context.next = 34;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return", 'exists');
|
||||
|
||||
case 34:
|
||||
if (forceBuild) _log.log.info('Reusing base binaries built locally:', built);
|
||||
return _context.abrupt("return", built);
|
||||
|
||||
case 36:
|
||||
if (forceBuild) {
|
||||
_context.next = 44;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
_context.next = 39;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return", 'fetched');
|
||||
|
||||
case 39:
|
||||
_context.next = 41;
|
||||
return cloud.download(remote, fetched);
|
||||
|
||||
case 41:
|
||||
if (!_context.sent) {
|
||||
_context.next = 43;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return", fetched);
|
||||
|
||||
case 43:
|
||||
fetchFailed = true;
|
||||
|
||||
case 44:
|
||||
if (!dryRun && fetchFailed) {
|
||||
_log.log.info('Not found in GitHub releases:', JSON.stringify(remote));
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
_log.log.info('Building base binary from source:', _path.default.basename(built));
|
||||
}
|
||||
|
||||
if (!(system.hostPlatform !== platform)) {
|
||||
_context.next = 48;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)(`Not able to build for '${opts.platform}' here, only for '${system.hostPlatform}'`);
|
||||
|
||||
case 48:
|
||||
if (!(system.hostArch !== arch)) {
|
||||
_context.next = 50;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)(`Not able to build for '${opts.arch}' here, only for '${system.hostArch}'`);
|
||||
|
||||
case 50:
|
||||
if (!(system.knownArchs.indexOf(arch) < 0)) {
|
||||
_context.next = 52;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)(`Unknown arch '${opts.arch}'. Specify ${system.knownArchs.join(', ')}`);
|
||||
|
||||
case 52:
|
||||
if (!dryRun) {
|
||||
_context.next = 54;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("return", 'built');
|
||||
|
||||
case 54:
|
||||
_context.next = 56;
|
||||
return (0, _build.default)(nodeVersion, arch, built);
|
||||
|
||||
case 56:
|
||||
return _context.abrupt("return", built);
|
||||
|
||||
case 57:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee);
|
||||
}));
|
||||
return _need.apply(this, arguments);
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.wasReported = wasReported;
|
||||
exports.log = void 0;
|
||||
|
||||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck.js"));
|
||||
|
||||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass.js"));
|
||||
|
||||
var _progress = _interopRequireDefault(require("progress"));
|
||||
|
||||
var _assert = _interopRequireDefault(require("assert"));
|
||||
|
||||
var _chalk = _interopRequireDefault(require("chalk"));
|
||||
|
||||
var Log =
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
function Log() {
|
||||
(0, _classCallCheck2.default)(this, Log);
|
||||
}
|
||||
|
||||
(0, _createClass2.default)(Log, [{
|
||||
key: "_lines",
|
||||
value: function _lines(lines) {
|
||||
if (lines === undefined) return;
|
||||
|
||||
if (!Array.isArray(lines)) {
|
||||
console.log(` ${lines}`);
|
||||
return;
|
||||
}
|
||||
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var line = _step.value;
|
||||
console.log(` ${line}`);
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "debug",
|
||||
value: function debug(text, lines) {
|
||||
if (!this.debugMode) return;
|
||||
console.log(`> ${_chalk.default.green('[debug]')} ${text}`);
|
||||
|
||||
this._lines(lines);
|
||||
}
|
||||
}, {
|
||||
key: "info",
|
||||
value: function info(text, lines) {
|
||||
console.log(`> ${text}`);
|
||||
|
||||
this._lines(lines);
|
||||
}
|
||||
}, {
|
||||
key: "warn",
|
||||
value: function warn(text, lines) {
|
||||
console.log(`> ${_chalk.default.blue('Warning')} ${text}`);
|
||||
|
||||
this._lines(lines);
|
||||
}
|
||||
}, {
|
||||
key: "error",
|
||||
value: function error(text, lines) {
|
||||
if (text.stack) text = text.stack;
|
||||
console.log(`> ${_chalk.default.red('Error!')} ${text}`);
|
||||
|
||||
this._lines(lines);
|
||||
}
|
||||
}, {
|
||||
key: "enableProgress",
|
||||
value: function enableProgress(text) {
|
||||
(0, _assert.default)(!this.bar);
|
||||
text += ' '.repeat(28 - text.length);
|
||||
this.bar = new _progress.default(` ${text} [:bar] :percent`, {
|
||||
stream: process.stdout,
|
||||
width: 20,
|
||||
complete: '=',
|
||||
incomplete: ' ',
|
||||
total: 100
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "showProgress",
|
||||
value: function showProgress(percentage) {
|
||||
if (!this.bar) return;
|
||||
this.bar.update(percentage / 100);
|
||||
}
|
||||
}, {
|
||||
key: "disableProgress",
|
||||
value: function disableProgress() {
|
||||
if (!this.bar) return; // avoid empty line
|
||||
|
||||
if (!this.bar.complete) {
|
||||
this.bar.terminate();
|
||||
}
|
||||
|
||||
delete this.bar;
|
||||
}
|
||||
}]);
|
||||
return Log;
|
||||
}();
|
||||
|
||||
var log = new Log();
|
||||
exports.log = log;
|
||||
|
||||
function wasReported(error, lines) {
|
||||
if (error === undefined) {
|
||||
error = new Error('No message');
|
||||
} else if (typeof error === 'string') {
|
||||
log.error(error, lines);
|
||||
error = new Error(error);
|
||||
}
|
||||
|
||||
error.wasReported = true;
|
||||
return error;
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.localPlace = localPlace;
|
||||
exports.remotePlace = remotePlace;
|
||||
|
||||
var _semver = require("semver");
|
||||
|
||||
var _expandTemplate = _interopRequireDefault(require("expand-template"));
|
||||
|
||||
var _os = _interopRequireDefault(require("os"));
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
var _places = _interopRequireDefault(require("../places.json"));
|
||||
|
||||
var expand = (0, _expandTemplate.default)();
|
||||
var PKG_CACHE_PATH = process.env.PKG_CACHE_PATH;
|
||||
|
||||
var cachePath = PKG_CACHE_PATH || _path.default.join(_os.default.homedir(), '.pkg-cache');
|
||||
|
||||
function tagFromVersion(version) {
|
||||
var mj = (0, _semver.major)(version);
|
||||
var mn = (0, _semver.minor)(version);
|
||||
return `v${mj}.${mn}`;
|
||||
}
|
||||
|
||||
function localPlace(opts) {
|
||||
var p = _places.default.localPlace;
|
||||
var version = opts.version;
|
||||
var tag = tagFromVersion(version);
|
||||
Object.assign(opts, {
|
||||
tag
|
||||
});
|
||||
|
||||
var atHome = _path.default.join(cachePath, p);
|
||||
|
||||
return expand(_path.default.resolve(atHome), opts);
|
||||
}
|
||||
|
||||
function remotePlace(opts) {
|
||||
var p = _places.default.remotePlace;
|
||||
var version = opts.version;
|
||||
var tag = tagFromVersion(version);
|
||||
Object.assign(opts, {
|
||||
tag
|
||||
});
|
||||
return {
|
||||
tag,
|
||||
name: expand(p, opts)
|
||||
};
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.spawn = spawn;
|
||||
exports.progress = progress;
|
||||
|
||||
var _byline = _interopRequireDefault(require("byline"));
|
||||
|
||||
var _child_process = _interopRequireDefault(require("child_process"));
|
||||
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var MAX_LINES = 20;
|
||||
var DEBUG_THRESHOLDS = false;
|
||||
|
||||
function errorLines(lines) {
|
||||
return lines.slice(-MAX_LINES).map(function (line) {
|
||||
return line[1];
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
function spawn(cmd, args, opts) {
|
||||
var child = _child_process.default.spawn(cmd, args, opts);
|
||||
|
||||
var stdout = (0, _byline.default)(child.stdout);
|
||||
var stderr = (0, _byline.default)(child.stderr);
|
||||
var lines = [];
|
||||
|
||||
var onData = function onData(data) {
|
||||
var time = new Date().getTime();
|
||||
lines.push([time, data.toString()]); // TODO chalk stdout/stderr?
|
||||
|
||||
var thresholds = this.thresholds; // eslint-disable-line no-invalid-this
|
||||
|
||||
if (thresholds) {
|
||||
for (var key in thresholds) {
|
||||
if (data.indexOf(key) >= 0) {
|
||||
var p = thresholds[key];
|
||||
|
||||
_log.log.showProgress(p);
|
||||
|
||||
if (DEBUG_THRESHOLDS) {
|
||||
lines.push([time, '************']);
|
||||
lines.push([time, p + ': ' + key]);
|
||||
lines.push([time, '************']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
child.on('error', function (error) {
|
||||
console.error(errorLines(lines)); // dont use `log` here
|
||||
|
||||
reject(error);
|
||||
});
|
||||
child.on('close', function (code) {
|
||||
if (code) {
|
||||
console.error(errorLines(lines)); // dont use `log` here
|
||||
|
||||
return reject(new Error(`${cmd} failed with code ${code}`));
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
onData = onData.bind(promise);
|
||||
if (stdout) stdout.on('data', onData);
|
||||
if (stderr) stderr.on('data', onData);
|
||||
promise.child = child;
|
||||
promise.lines = lines;
|
||||
return promise;
|
||||
}
|
||||
|
||||
function progress(promise, thresholds) {
|
||||
promise.thresholds = thresholds;
|
||||
var child = promise.child,
|
||||
lines = promise.lines;
|
||||
|
||||
_log.log.enableProgress(promise.child.spawnfile);
|
||||
|
||||
_log.log.showProgress(0);
|
||||
|
||||
var start = new Date().getTime();
|
||||
child.on('close', function () {
|
||||
if (DEBUG_THRESHOLDS) {
|
||||
var finish = new Date().getTime();
|
||||
var content = lines.map(function (line) {
|
||||
return (100 * (line[0] - start) / (finish - start) | 0) + ': ' + line[1];
|
||||
}).join('\n');
|
||||
|
||||
_fs.default.writeFileSync(child.spawnfile + '.debug', content);
|
||||
}
|
||||
|
||||
_log.log.showProgress(100);
|
||||
|
||||
_log.log.disableProgress();
|
||||
});
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.abiToNodeRange = abiToNodeRange;
|
||||
exports.isValidNodeRange = isValidNodeRange;
|
||||
exports.toFancyPlatform = toFancyPlatform;
|
||||
exports.toFancyArch = toFancyArch;
|
||||
exports.knownArchs = exports.targetArchs = exports.hostArch = exports.knownPlatforms = exports.hostPlatform = exports.hostAbi = void 0;
|
||||
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
|
||||
var _child_process = require("child_process");
|
||||
|
||||
function getHostAbi() {
|
||||
return 'm' + process.versions.modules;
|
||||
}
|
||||
|
||||
function abiToNodeRange(abi) {
|
||||
if (/^m?14/.test(abi)) return 'node0.12';
|
||||
if (/^m?46/.test(abi)) return 'node4';
|
||||
if (/^m?47/.test(abi)) return 'node5';
|
||||
if (/^m?48/.test(abi)) return 'node6';
|
||||
if (/^m?51/.test(abi)) return 'node7';
|
||||
if (/^m?57/.test(abi)) return 'node8';
|
||||
if (/^m?59/.test(abi)) return 'node9';
|
||||
return abi;
|
||||
}
|
||||
|
||||
function isValidNodeRange(nodeRange) {
|
||||
if (nodeRange === 'latest') return true;
|
||||
if (!/^node/.test(nodeRange)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function toFancyPlatform(platform) {
|
||||
if (platform === 'darwin') return 'macos';
|
||||
if (platform === 'lin') return 'linux';
|
||||
if (platform === 'mac') return 'macos';
|
||||
if (platform === 'osx') return 'macos';
|
||||
if (platform === 'win32') return 'win';
|
||||
if (platform === 'windows') return 'win';
|
||||
return platform;
|
||||
}
|
||||
|
||||
function detectAlpine() {
|
||||
var _process = process,
|
||||
platform = _process.platform;
|
||||
if (platform !== 'linux') return false; // https://github.com/sass/node-sass/issues/1589#issuecomment-265292579
|
||||
|
||||
var ldd = (0, _child_process.spawnSync)('ldd').stderr.toString();
|
||||
if (/\bmusl\b/.test(ldd)) return true;
|
||||
var lddNode = (0, _child_process.spawnSync)('ldd', [process.execPath]).stdout.toString();
|
||||
return /\bmusl\b/.test(lddNode);
|
||||
}
|
||||
|
||||
var isAlpine = detectAlpine();
|
||||
|
||||
function getHostPlatform() {
|
||||
var _process2 = process,
|
||||
platform = _process2.platform;
|
||||
if (isAlpine) return 'alpine';
|
||||
return toFancyPlatform(platform);
|
||||
}
|
||||
|
||||
function getKnownPlatforms() {
|
||||
return ['alpine', 'freebsd', 'linux', 'macos', 'win'];
|
||||
}
|
||||
|
||||
function toFancyArch(arch) {
|
||||
if (arch === 'ia32') return 'x86';
|
||||
if (arch === 'x86_64') return 'x64';
|
||||
return arch;
|
||||
}
|
||||
|
||||
function getArmHostArch() {
|
||||
var cpu = _fs.default.readFileSync('/proc/cpuinfo', 'utf8');
|
||||
|
||||
if (cpu.indexOf('vfpv3') >= 0) return 'armv7';
|
||||
var name = cpu.split('model name')[1];
|
||||
if (name) name = name.split(':')[1];
|
||||
if (name) name = name.split('\n')[0];
|
||||
if (name && name.indexOf('ARMv7') >= 0) return 'armv7';
|
||||
return 'armv6';
|
||||
}
|
||||
|
||||
function getHostArch() {
|
||||
var _process3 = process,
|
||||
arch = _process3.arch;
|
||||
if (arch === 'arm') return getArmHostArch();
|
||||
return toFancyArch(arch);
|
||||
}
|
||||
|
||||
function getTargetArchs() {
|
||||
var arch = getHostArch();
|
||||
if (arch === 'x64') return ['x64', 'x86'];
|
||||
return [arch];
|
||||
}
|
||||
|
||||
function getKnownArchs() {
|
||||
return ['x64', 'x86', 'armv6', 'armv7', 'arm64', 's390x'];
|
||||
}
|
||||
|
||||
var hostAbi = getHostAbi();
|
||||
exports.hostAbi = hostAbi;
|
||||
var hostPlatform = getHostPlatform();
|
||||
exports.hostPlatform = hostPlatform;
|
||||
var knownPlatforms = getKnownPlatforms();
|
||||
exports.knownPlatforms = knownPlatforms;
|
||||
var hostArch = getHostArch();
|
||||
exports.hostArch = hostArch;
|
||||
var targetArchs = getTargetArchs();
|
||||
exports.targetArchs = targetArchs;
|
||||
var knownArchs = getKnownArchs();
|
||||
exports.knownArchs = knownArchs;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.tempPath = tempPath;
|
||||
|
||||
var _uniqueTempDir = _interopRequireDefault(require("unique-temp-dir"));
|
||||
|
||||
function tempPath() {
|
||||
return _uniqueTempDir.default.apply(void 0, arguments);
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = thresholds;
|
||||
|
||||
var _assert = _interopRequireDefault(require("assert"));
|
||||
|
||||
/* eslint-disable key-spacing */
|
||||
|
||||
/* eslint-disable no-multi-spaces */
|
||||
function thresholds(cmd, nodeVersion) {
|
||||
if (cmd === 'clone') {
|
||||
return {
|
||||
'ving objects: 0%': 0,
|
||||
'ving objects: 1%': 1,
|
||||
'ving objects: 6%': 5,
|
||||
'ving objects: 12%': 10,
|
||||
'ving objects: 25%': 20,
|
||||
'ving objects: 50%': 40,
|
||||
'ving objects: 75%': 60,
|
||||
'deltas: 0%': 80,
|
||||
'deltas: 50%': 90
|
||||
};
|
||||
} else if (cmd === 'vcbuild') {
|
||||
if (/^v?0/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'openssl.vcxproj ->': 9,
|
||||
'v8_base.vcxproj ->': 55,
|
||||
'mksnapshot.vcxproj ->': 76,
|
||||
'node\\Release\\node.exp': 90
|
||||
};
|
||||
} else if (/^v?4/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'hydrogen-representation-changes.cc': 13,
|
||||
'openssl.vcxproj ->': 21,
|
||||
'v8_base_0.vcxproj ->': 35,
|
||||
'build\\Release\\mksnapshot.lib': 57,
|
||||
'mksnapshot.vcxproj ->': 67,
|
||||
'node\\Release\\node.exp': 85,
|
||||
'cctest.vcxproj ->': 97
|
||||
};
|
||||
} else if (/^v?6/.test(nodeVersion)) {
|
||||
return {
|
||||
'http_parser.vcxproj ->': 1,
|
||||
'openssl.vcxproj ->': 4,
|
||||
'icudata.vcxproj ->': 10,
|
||||
'hydrogen-representation-changes.cc': 15,
|
||||
'interface-descriptors-x64.cc': 27,
|
||||
'v8_base_0.vcxproj ->': 41,
|
||||
'build\\Release\\mksnapshot.lib': 55,
|
||||
'mksnapshot.vcxproj ->': 66,
|
||||
'node\\Release\\node.exp': 82,
|
||||
'cctest.vcxproj ->': 95
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else if (cmd === 'make') {
|
||||
if (/^v?0/.test(nodeVersion)) {
|
||||
return {
|
||||
'openssl/crypto/ex_data.o.d.raw': 10,
|
||||
'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/js-graph.o.d.raw': 30,
|
||||
'v8/src/debug.o.d.raw': 40,
|
||||
'v8/src/heap/spaces.o.d.raw': 50,
|
||||
'v8/src/hydrogen-sce.o.d.raw': 60,
|
||||
'v8/src/parser.o.d.raw': 70,
|
||||
'v8/src/token.o.d.raw': 80,
|
||||
'v8/src/x64/stub-cache-x64.o.d.raw': 90
|
||||
};
|
||||
} else if (/^v?4/.test(nodeVersion)) {
|
||||
return {
|
||||
'v8/src/compiler/code-generator.o.d.raw': 10,
|
||||
'v8/src/compiler/operator.o.d.raw': 20,
|
||||
'v8/src/factory.o.d.raw': 30,
|
||||
'v8/src/hydrogen.o.d.raw': 40,
|
||||
'v8/src/liveedit.o.d.raw': 50,
|
||||
'v8/src/runtime/runtime-function.o.d.raw': 60,
|
||||
'v8/src/v8.o.d.raw': 70,
|
||||
'v8_nosnapshot/gen/libraries.o.d.raw': 80,
|
||||
'openssl/crypto/ex_data.o.d.raw': 90
|
||||
};
|
||||
} else if (/^v?6/.test(nodeVersion)) {
|
||||
return {
|
||||
'icuucx/deps/icu-small/source/common/parsepos.o.d.raw': 10,
|
||||
'v8/src/api.o.d.raw': 20,
|
||||
'v8/src/compiler/graph-replay.o.d.raw': 30,
|
||||
'v8/src/compiler.o.d.raw': 40,
|
||||
'v8/src/date.o.d.raw': 50,
|
||||
'v8/src/isolate.o.d.raw': 60,
|
||||
'v8/src/runtime/runtime-function.o.d.raw': 70,
|
||||
'v8/src/x64/assembler-x64.o.d.raw': 80,
|
||||
'icui18n/deps/icu-small/source/i18n/search.o.d.raw': 90
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
(0, _assert.default)(false);
|
||||
}
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.dontBuild = dontBuild;
|
||||
exports.main = main;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _system = require("./system.js");
|
||||
|
||||
var _places = require("./places.js");
|
||||
|
||||
var _log = require("./log.js");
|
||||
|
||||
var _cloud = require("./cloud.js");
|
||||
|
||||
var _build = _interopRequireDefault(require("./build.js"));
|
||||
|
||||
var _patches = _interopRequireDefault(require("../patches/patches.json"));
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
var _verify = require("./verify.js");
|
||||
|
||||
var _package = require("../package.json");
|
||||
|
||||
var cloud = new _cloud.Cloud({
|
||||
owner: 'zeit',
|
||||
repo: 'pkg-fetch'
|
||||
});
|
||||
|
||||
function dontBuild(nodeVersion, targetPlatform, targetArch) {
|
||||
// binaries are not provided for x86 anymore
|
||||
if (targetPlatform !== 'win' && targetArch === 'x86') return true; // https://support.apple.com/en-us/HT201948
|
||||
// don't disable macos-x86 because it is not possible
|
||||
// to cross-compile for x86 from macos otherwise
|
||||
|
||||
var major = nodeVersion.match(/^v?(\d+)/)[1] | 0; // node 0.12 does not compile on arm
|
||||
|
||||
if (/^arm/.test(targetArch) && major === 0) return true;
|
||||
if (targetPlatform === 'freebsd' && major < 4) return true;
|
||||
if (targetPlatform === 'alpine' && (targetArch !== 'x64' || major < 6)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function main() {
|
||||
return _main.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _main() {
|
||||
_main = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee() {
|
||||
var nodeVersion, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, targetArch, local, remote, short;
|
||||
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
if (process.env.GITHUB_USERNAME) {
|
||||
_context.next = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
throw (0, _log.wasReported)('No github credentials. Upload will fail!');
|
||||
|
||||
case 2:
|
||||
_context.t0 = _index.default.keys(_patches.default);
|
||||
|
||||
case 3:
|
||||
if ((_context.t1 = _context.t0()).done) {
|
||||
_context.next = 56;
|
||||
break;
|
||||
}
|
||||
|
||||
nodeVersion = _context.t1.value;
|
||||
_iteratorNormalCompletion = true;
|
||||
_didIteratorError = false;
|
||||
_iteratorError = undefined;
|
||||
_context.prev = 8;
|
||||
_iterator = _system.targetArchs[Symbol.iterator]();
|
||||
|
||||
case 10:
|
||||
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
|
||||
_context.next = 40;
|
||||
break;
|
||||
}
|
||||
|
||||
targetArch = _step.value;
|
||||
|
||||
if (!dontBuild(nodeVersion, _system.hostPlatform, targetArch)) {
|
||||
_context.next = 14;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("continue", 37);
|
||||
|
||||
case 14:
|
||||
local = (0, _places.localPlace)({
|
||||
from: 'built',
|
||||
arch: targetArch,
|
||||
nodeVersion,
|
||||
platform: _system.hostPlatform,
|
||||
version: _package.version
|
||||
});
|
||||
remote = (0, _places.remotePlace)({
|
||||
arch: targetArch,
|
||||
nodeVersion,
|
||||
platform: _system.hostPlatform,
|
||||
version: _package.version
|
||||
});
|
||||
_context.next = 18;
|
||||
return cloud.alreadyUploaded(remote);
|
||||
|
||||
case 18:
|
||||
if (!_context.sent) {
|
||||
_context.next = 20;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context.abrupt("continue", 37);
|
||||
|
||||
case 20:
|
||||
short = _path.default.basename(local);
|
||||
|
||||
_log.log.info(`Building ${short}...`);
|
||||
|
||||
_context.next = 24;
|
||||
return (0, _build.default)(nodeVersion, targetArch, local);
|
||||
|
||||
case 24:
|
||||
_log.log.info(`Verifying ${short}...`);
|
||||
|
||||
_context.next = 27;
|
||||
return (0, _verify.verify)(local);
|
||||
|
||||
case 27:
|
||||
_log.log.info(`Uploading ${short}...`);
|
||||
|
||||
_context.prev = 28;
|
||||
_context.next = 31;
|
||||
return cloud.upload(local, remote);
|
||||
|
||||
case 31:
|
||||
_context.next = 37;
|
||||
break;
|
||||
|
||||
case 33:
|
||||
_context.prev = 33;
|
||||
_context.t2 = _context["catch"](28);
|
||||
// TODO catch only network errors
|
||||
if (!_context.t2.wasReported) _log.log.error(_context.t2);
|
||||
|
||||
_log.log.info('Meanwhile i will continue making binaries');
|
||||
|
||||
case 37:
|
||||
_iteratorNormalCompletion = true;
|
||||
_context.next = 10;
|
||||
break;
|
||||
|
||||
case 40:
|
||||
_context.next = 46;
|
||||
break;
|
||||
|
||||
case 42:
|
||||
_context.prev = 42;
|
||||
_context.t3 = _context["catch"](8);
|
||||
_didIteratorError = true;
|
||||
_iteratorError = _context.t3;
|
||||
|
||||
case 46:
|
||||
_context.prev = 46;
|
||||
_context.prev = 47;
|
||||
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
|
||||
case 49:
|
||||
_context.prev = 49;
|
||||
|
||||
if (!_didIteratorError) {
|
||||
_context.next = 52;
|
||||
break;
|
||||
}
|
||||
|
||||
throw _iteratorError;
|
||||
|
||||
case 52:
|
||||
return _context.finish(49);
|
||||
|
||||
case 53:
|
||||
return _context.finish(46);
|
||||
|
||||
case 54:
|
||||
_context.next = 3;
|
||||
break;
|
||||
|
||||
case 56:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, null, [[8, 42, 46, 54], [28, 33], [47,, 49, 53]]);
|
||||
}));
|
||||
return _main.apply(this, arguments);
|
||||
}
|
||||
|
||||
if (!module.parent) {
|
||||
main().catch(function (error) {
|
||||
if (!error.wasReported) _log.log.error(error);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault.js");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.verify = verify;
|
||||
|
||||
var _index = _interopRequireDefault(require("@babel/runtime/regenerator/index.js"));
|
||||
|
||||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator.js"));
|
||||
|
||||
var _chmod = require("./chmod.js");
|
||||
|
||||
var _spawn = require("./spawn.js");
|
||||
|
||||
var script = `
|
||||
var vm = require('vm');
|
||||
var assert = require('assert');
|
||||
var text = '(function () { return 42; })';
|
||||
var cd, fn, result;
|
||||
var modules = process.versions.modules | 0;
|
||||
var v8 = process.versions.v8.split('.').slice(0, 2).join('.');
|
||||
|
||||
var s1 = new vm.Script(text, { filename: 's1', produceCachedData: true, sourceless: true });
|
||||
assert(s1.cachedDataProduced);
|
||||
cd = s1.cachedData;
|
||||
|
||||
var kCpuFeaturesOffset, cpuFeatures;
|
||||
|
||||
if (modules === 14) {
|
||||
} else
|
||||
if (modules === 46 || modules === 48 || modules === 51) {
|
||||
kCpuFeaturesOffset = 0x0c;
|
||||
} else
|
||||
if (modules === 57) {
|
||||
if (v8 === '6.2') {
|
||||
kCpuFeaturesOffset = 0x0c;
|
||||
} else
|
||||
if (v8 === '5.8') {
|
||||
kCpuFeaturesOffset = 0x0c;
|
||||
} else {
|
||||
kCpuFeaturesOffset = 0x10;
|
||||
}
|
||||
} else
|
||||
if (modules === 59) {
|
||||
kCpuFeaturesOffset = 0x0c;
|
||||
} else
|
||||
if (modules === 64) {
|
||||
kCpuFeaturesOffset = 0x0c;
|
||||
} else
|
||||
if (modules === 72) {
|
||||
// no cpu features anymore
|
||||
} else {
|
||||
assert(false, modules);
|
||||
}
|
||||
|
||||
if (modules >= 46 && // no cpu_features field in 0.12
|
||||
process.arch !== 'arm' && // non-zero features even in sourceless mode in arm
|
||||
modules < 72) { // no cpu_features field in 12+
|
||||
cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset);
|
||||
assert(cpuFeatures === 0, 'CPU_FEATURES must be zero');
|
||||
}
|
||||
|
||||
var s2 = new vm.Script(undefined, { filename: 's2', cachedData: cd, sourceless: true });
|
||||
fn = s2.runInThisContext();
|
||||
result = fn();
|
||||
assert.equal(result, 42);
|
||||
|
||||
if (modules === 14) {
|
||||
} else
|
||||
if (modules === 46 || modules === 48 ||
|
||||
modules === 51 || modules === 57 || modules === 59 || modules === 64) {
|
||||
var paddedPayloadOffset = 0x48; // see SerializedCodeData::Payload()
|
||||
var index = paddedPayloadOffset + 10;
|
||||
cd[index] ^= 0xf0;
|
||||
var s3 = new vm.Script(undefined, { filename: 's3', cachedData: cd, sourceless: true });
|
||||
assert(s3.cachedDataRejected, 's3.cachedDataRejected must be true');
|
||||
} else
|
||||
if (modules === 72) {
|
||||
} else {
|
||||
assert(false, modules);
|
||||
}
|
||||
|
||||
var s4 = new vm.Script(text, { filename: 's4', produceCachedData: true });
|
||||
assert(s4.cachedDataProduced, 's4.cachedDataProduced must be true');
|
||||
cd = s4.cachedData;
|
||||
|
||||
if (modules >= 46 && // no cpu_features field in 0.12
|
||||
process.arch !== 'arm' && // zero features even in non-sourceless mode in arm
|
||||
modules < 72) { // no cpu_features field in 12+
|
||||
cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset);
|
||||
assert(cpuFeatures !== 0, 'CPU_FEATURES must be non-zero');
|
||||
}
|
||||
|
||||
console.log('ok');
|
||||
`;
|
||||
|
||||
function verify(_x) {
|
||||
return _verify.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _verify() {
|
||||
_verify = (0, _asyncToGenerator2.default)(
|
||||
/*#__PURE__*/
|
||||
_index.default.mark(function _callee(local) {
|
||||
return _index.default.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.next = 2;
|
||||
return (0, _chmod.plusx)(local);
|
||||
|
||||
case 2:
|
||||
_context.next = 4;
|
||||
return (0, _spawn.spawn)(local, ['-e', script], {
|
||||
env: {
|
||||
PKG_EXECPATH: 'PKG_INVOKE_NODEJS'
|
||||
}
|
||||
});
|
||||
|
||||
case 4:
|
||||
case "end":
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee);
|
||||
}));
|
||||
return _verify.apply(this, arguments);
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Zeit, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"_from": "pkg-fetch@^2.6.4",
|
||||
"_id": "pkg-fetch@2.6.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-4j4jiuo6RRIuD9e9xUE6OQYnIkQCArZjkHXNYsSJjxhJeiHE16MA+rENMblvGLbeWsTY3BPfcYVCGFXzpfJetA==",
|
||||
"_location": "/pkg-fetch",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "pkg-fetch@^2.6.4",
|
||||
"name": "pkg-fetch",
|
||||
"escapedName": "pkg-fetch",
|
||||
"rawSpec": "^2.6.4",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^2.6.4"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/pkg"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.6.4.tgz",
|
||||
"_shasum": "0faac4c4ae9668e1daf9819180606966a5e33f96",
|
||||
"_spec": "pkg-fetch@^2.6.4",
|
||||
"_where": "/home/miti99/Dropbox/Workspace/FBcount/Nodejs/node_modules/pkg",
|
||||
"ava": {
|
||||
"failFast": true,
|
||||
"files": [
|
||||
"test/*.test.js"
|
||||
],
|
||||
"require": [
|
||||
"@babel/register"
|
||||
]
|
||||
},
|
||||
"babel": {
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-async-to-generator",
|
||||
"@babel/plugin-transform-runtime"
|
||||
],
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "4"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"bin": {
|
||||
"pkg-fetch": "lib-es5/bin.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/zeit/pkg-fetch/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.5",
|
||||
"byline": "^5.0.0",
|
||||
"chalk": "^3.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
"fs-extra": "^8.1.0",
|
||||
"minimist": "^1.2.0",
|
||||
"progress": "^2.0.3",
|
||||
"request": "^2.88.0",
|
||||
"request-progress": "^3.0.0",
|
||||
"semver": "^6.3.0",
|
||||
"unique-temp-dir": "^1.0.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Compiles and stores base binaries for pkg",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.7.5",
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.7.4",
|
||||
"@babel/plugin-transform-runtime": "^7.7.5",
|
||||
"@babel/preset-env": "^7.7.5",
|
||||
"@babel/register": "^7.7.4",
|
||||
"ava": "^2.4.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-config-klopov": "^1.0.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "klopov",
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"files": [
|
||||
"lib-es5/*.js",
|
||||
"patches/*",
|
||||
"places.json"
|
||||
],
|
||||
"homepage": "https://github.com/zeit/pkg-fetch#readme",
|
||||
"license": "MIT",
|
||||
"main": "lib-es5/index.js",
|
||||
"name": "pkg-fetch",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/zeit/pkg-fetch.git"
|
||||
},
|
||||
"scripts": {
|
||||
"babel": "node test/rimraf-es5.js && babel lib --out-dir lib-es5",
|
||||
"bin": "node lib-es5/bin.js",
|
||||
"lint": "eslint-klopov . || true",
|
||||
"prepare": "npm run babel",
|
||||
"prepublishOnly": "eslint-klopov . && npm test",
|
||||
"start": "node lib-es5/upload.js",
|
||||
"test": "ava"
|
||||
},
|
||||
"version": "2.6.4"
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <fedor@indutny.com>
|
||||
Date: Wed, 20 Jan 2016 19:34:19 -0500
|
||||
Subject: vm: introduce `cachedData`/`produceCachedData`
|
||||
|
||||
Introduce `cachedData`/`produceCachedData` options for `v8.Script`.
|
||||
Could be used to consume/produce V8's code cache for speeding up
|
||||
compilation of known code.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/4777
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 2e8fd2c..1b3d618 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
+#include "node_buffer.h"
|
||||
#include "node_internals.h"
|
||||
#include "node_watchdog.h"
|
||||
#include "base-object.h"
|
||||
#include "base-object-inl.h"
|
||||
#include "env.h"
|
||||
@@ -484,28 +485,60 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
TryCatch try_catch;
|
||||
Local<String> code = args[0]->ToString();
|
||||
Local<String> filename = GetFilenameArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
+ Local<Value> cached_data_buf = GetCachedData(args, 1);
|
||||
+ bool produce_cached_data = GetProduceCachedData(args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
+ ScriptCompiler::CachedData* cached_data = NULL;
|
||||
+ if (!cached_data_buf.IsEmpty()) {
|
||||
+ cached_data = new ScriptCompiler::CachedData(
|
||||
+ reinterpret_cast<uint8_t*>(Buffer::Data(cached_data_buf)),
|
||||
+ Buffer::Length(cached_data_buf));
|
||||
+ }
|
||||
+
|
||||
ScriptOrigin origin(filename);
|
||||
- ScriptCompiler::Source source(code, origin);
|
||||
- Local<UnboundScript> v8_script =
|
||||
- ScriptCompiler::CompileUnbound(env->isolate(), &source);
|
||||
+ ScriptCompiler::Source source(code, origin, cached_data);
|
||||
+ ScriptCompiler::CompileOptions compile_options =
|
||||
+ ScriptCompiler::kNoCompileOptions;
|
||||
+
|
||||
+ if (source.GetCachedData() != NULL)
|
||||
+ compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
+ else if (produce_cached_data)
|
||||
+ compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
+
|
||||
+ Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ env->isolate(),
|
||||
+ &source,
|
||||
+ compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+
|
||||
+ if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ // no 'rejected' field in cachedData
|
||||
+ } else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
+ Local<Object> buf = Buffer::New(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedData");
|
||||
+ args.This()->Set(cached_data_string, buf);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
return !value.IsEmpty() &&
|
||||
@@ -656,10 +689,46 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
return value->IsUndefined() ? defaultFilename : value->ToString();
|
||||
}
|
||||
|
||||
|
||||
+ static Local<Value> GetCachedData(
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "cachedData");
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(key);
|
||||
+ if (value->IsUndefined()) {
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+
|
||||
+ if (!Buffer::HasInstance(value)) {
|
||||
+ Environment::ThrowTypeError(
|
||||
+ args.GetIsolate(),
|
||||
+ "options.cachedData must be a Buffer instance");
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ static bool GetProduceCachedData(
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "produceCachedData");
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(key);
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static bool EvalMachine(Environment* env,
|
||||
const int64_t timeout,
|
||||
const bool display_errors,
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
TryCatch& try_catch) {
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <fedor@indutny.com>
|
||||
Date: Wed, 20 Jan 2016 19:34:19 -0500
|
||||
Subject: vm: introduce `cachedData`/`produceCachedData`
|
||||
|
||||
Introduce `cachedData`/`produceCachedData` options for `v8.Script`.
|
||||
Could be used to consume/produce V8's code cache for speeding up
|
||||
compilation of known code.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/4777
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 7b6ffc8..5c99f80 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -53,10 +53,12 @@ namespace node {
|
||||
V(blocks_string, "blocks") \
|
||||
V(buffer_string, "buffer") \
|
||||
V(bytes_string, "bytes") \
|
||||
V(bytes_parsed_string, "bytesParsed") \
|
||||
V(bytes_read_string, "bytesRead") \
|
||||
+ V(cached_data_string, "cachedData") \
|
||||
+ V(cached_data_rejected_string, "cachedDataRejected") \
|
||||
V(callback_string, "callback") \
|
||||
V(change_string, "change") \
|
||||
V(oncertcb_string, "oncertcb") \
|
||||
V(onclose_string, "_onclose") \
|
||||
V(code_string, "code") \
|
||||
@@ -165,10 +167,11 @@ namespace node {
|
||||
V(pipe_string, "pipe") \
|
||||
V(port_string, "port") \
|
||||
V(preference_string, "preference") \
|
||||
V(priority_string, "priority") \
|
||||
V(processed_string, "processed") \
|
||||
+ V(produce_cached_data_string, "produceCachedData") \
|
||||
V(prototype_string, "prototype") \
|
||||
V(raw_string, "raw") \
|
||||
V(rdev_string, "rdev") \
|
||||
V(readable_string, "readable") \
|
||||
V(received_shutdown_string, "receivedShutdown") \
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 7404bbb..ecf9444 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "node.h"
|
||||
+#include "node_buffer.h"
|
||||
#include "node_internals.h"
|
||||
#include "node_watchdog.h"
|
||||
#include "base-object.h"
|
||||
#include "base-object-inl.h"
|
||||
#include "env.h"
|
||||
@@ -11,10 +12,11 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::AccessType;
|
||||
using v8::Array;
|
||||
+using v8::ArrayBuffer;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::Debug;
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::External;
|
||||
@@ -474,28 +476,61 @@ class ContextifyScript : public BaseObject {
|
||||
Local<String> code = args[0]->ToString(env->isolate());
|
||||
Local<String> filename = GetFilenameArg(args, 1);
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
+ MaybeLocal<Value> cached_data_buf = GetCachedData(env, args, 1);
|
||||
+ bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
+ ScriptCompiler::CachedData* cached_data = nullptr;
|
||||
+ if (!cached_data_buf.IsEmpty()) {
|
||||
+ auto cached_data_local = cached_data_buf.ToLocalChecked();
|
||||
+ cached_data = new ScriptCompiler::CachedData(
|
||||
+ reinterpret_cast<uint8_t*>(Buffer::Data(cached_data_local)),
|
||||
+ Buffer::Length(cached_data_local));
|
||||
+ }
|
||||
+
|
||||
ScriptOrigin origin(filename, lineOffset, columnOffset);
|
||||
- ScriptCompiler::Source source(code, origin);
|
||||
- Local<UnboundScript> v8_script =
|
||||
- ScriptCompiler::CompileUnbound(env->isolate(), &source);
|
||||
+ ScriptCompiler::Source source(code, origin, cached_data);
|
||||
+ ScriptCompiler::CompileOptions compile_options =
|
||||
+ ScriptCompiler::kNoCompileOptions;
|
||||
+
|
||||
+ if (source.GetCachedData() != nullptr)
|
||||
+ compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
+ else if (produce_cached_data)
|
||||
+ compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
+
|
||||
+ Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ env->isolate(),
|
||||
+ &source,
|
||||
+ compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+
|
||||
+ if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ args.This()->Set(
|
||||
+ env->cached_data_rejected_string(),
|
||||
+ Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
+ } else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
+ MaybeLocal<Object> buf = Buffer::Copy(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
return !value.IsEmpty() &&
|
||||
@@ -644,10 +679,47 @@ class ContextifyScript : public BaseObject {
|
||||
return defaultFilename;
|
||||
return value->ToString(args.GetIsolate());
|
||||
}
|
||||
|
||||
|
||||
+ static MaybeLocal<Value> GetCachedData(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(env->cached_data_string());
|
||||
+ if (value->IsUndefined()) {
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+
|
||||
+ if (!Buffer::HasInstance(value)) {
|
||||
+ Environment::ThrowTypeError(
|
||||
+ args.GetIsolate(),
|
||||
+ "options.cachedData must be a Buffer instance");
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ static bool GetProduceCachedData(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->produce_cached_data_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
From 16b0a8c1acb97a84e9a6e1868d600c525f27b0ec Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <mic.besace@gmail.com>
|
||||
Date: Mon, 8 Feb 2016 22:36:40 +0100
|
||||
Subject: src: replace usage of deprecated CompileUnbound
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5159
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index ecf9444..8769b53 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -501,11 +501,11 @@ class ContextifyScript : public BaseObject {
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
- Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
@@ -513,11 +513,12 @@ class ContextifyScript : public BaseObject {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
- contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+ contextify_script->script_.Reset(env->isolate(),
|
||||
+ v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001
|
||||
From: Jiho Choi <jray319@gmail.com>
|
||||
Date: Sat, 20 Feb 2016 20:44:06 -0600
|
||||
Subject: vm: fix `produceCachedData`
|
||||
|
||||
Fix segmentation faults when compiling the same code with
|
||||
`produceCachedData` option. V8 ignores the option when the code is in
|
||||
its compilation cache and does not return cached data. Added
|
||||
`cachedDataProduced` property to `v8.Script` to denote whether the
|
||||
cached data is produced successfully.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5343
|
||||
Reviewed-By: Fedor Indutny <fedor@indutny.com>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 1b3d618..dfc51e9 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -527,17 +527,25 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
// no 'rejected' field in cachedData
|
||||
} else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
- Local<Object> buf = Buffer::New(
|
||||
- env,
|
||||
- reinterpret_cast<const char*>(cached_data->data),
|
||||
- cached_data->length);
|
||||
- Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
- args.GetIsolate(), "cachedData");
|
||||
- args.This()->Set(cached_data_string, buf);
|
||||
+ bool cached_data_produced = cached_data != NULL;
|
||||
+ if (cached_data_produced) {
|
||||
+ Local<Object> buf = Buffer::New(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedData");
|
||||
+ args.This()->Set(cached_data_string, buf);
|
||||
+ }
|
||||
+ Local<String> cached_data_produced_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedDataProduced");
|
||||
+ args.This()->Set(
|
||||
+ cached_data_produced_string,
|
||||
+ Boolean::New(env->isolate(), cached_data_produced));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001
|
||||
From: Jiho Choi <jray319@gmail.com>
|
||||
Date: Sat, 20 Feb 2016 20:44:06 -0600
|
||||
Subject: vm: fix `produceCachedData`
|
||||
|
||||
Fix segmentation faults when compiling the same code with
|
||||
`produceCachedData` option. V8 ignores the option when the code is in
|
||||
its compilation cache and does not return cached data. Added
|
||||
`cachedDataProduced` property to `v8.Script` to denote whether the
|
||||
cached data is produced successfully.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5343
|
||||
Reviewed-By: Fedor Indutny <fedor@indutny.com>
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 5c99f80..c0b6dcd 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -54,10 +54,11 @@ namespace node {
|
||||
V(buffer_string, "buffer") \
|
||||
V(bytes_string, "bytes") \
|
||||
V(bytes_parsed_string, "bytesParsed") \
|
||||
V(bytes_read_string, "bytesRead") \
|
||||
V(cached_data_string, "cachedData") \
|
||||
+ V(cached_data_produced_string, "cachedDataProduced") \
|
||||
V(cached_data_rejected_string, "cachedDataRejected") \
|
||||
V(callback_string, "callback") \
|
||||
V(change_string, "change") \
|
||||
V(oncertcb_string, "oncertcb") \
|
||||
V(onclose_string, "_onclose") \
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 8769b53..4f63c20 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -522,15 +522,21 @@ class ContextifyScript : public BaseObject {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
} else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
- MaybeLocal<Object> buf = Buffer::Copy(
|
||||
- env,
|
||||
- reinterpret_cast<const char*>(cached_data->data),
|
||||
- cached_data->length);
|
||||
- args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ bool cached_data_produced = cached_data != nullptr;
|
||||
+ if (cached_data_produced) {
|
||||
+ MaybeLocal<Object> buf = Buffer::Copy(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ }
|
||||
+ args.This()->Set(
|
||||
+ env->cached_data_produced_string(),
|
||||
+ Boolean::New(env->isolate(), cached_data_produced));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
commit b324d0bb99045fcfe80397a978eb2ce29af4990f
|
||||
Author: igorklopov <igor@klopov.com>
|
||||
Date: Mon Aug 17 11:31:50 2015 +0400
|
||||
|
||||
some older revisions mixed together
|
||||
|
||||
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
||||
index 0e68ab8..92aca16 100644
|
||||
--- node/deps/v8/src/code-stubs.cc
|
||||
+++ node/deps/v8/src/code-stubs.cc
|
||||
@@ -252,6 +252,172 @@ void CodeStub::PrintName(OStream& os) const { // NOLINT
|
||||
}
|
||||
|
||||
|
||||
+void CheckCodeStub(CodeStub* pstub, CodeStub::Major MajorKey, int MinorKey) {
|
||||
+ if (pstub->MajorKey() != MajorKey) fprintf(stderr, "MajorKey %d != %d in %s\n", pstub->MajorKey(), MajorKey, pstub->MajorName(MajorKey, false));
|
||||
+ if (pstub->MinorKey() != MinorKey) fprintf(stderr, "MinorKey %d != %d in %s\n", pstub->MinorKey(), MinorKey, pstub->MajorName(MajorKey, false));
|
||||
+ // if (pstub->MajorKey() == MajorKey) fprintf(stderr, "correct MajorKey in %s\n", pstub->MajorName(MajorKey, false));
|
||||
+ // if (pstub->MinorKey() == MinorKey) fprintf(stderr, "correct MinorKey in %s\n", pstub->MajorName(MajorKey, false));
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
|
||||
+ DispatchedCall call) {
|
||||
+ CodeStub::Major MajorKey = MajorKeyFromKey(key);
|
||||
+ int MinorKey = MinorKeyFromKey(key);
|
||||
+ switch (MajorKey) {
|
||||
+ case CEntry: {
|
||||
+ // int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
|
||||
+ int result_size = (MinorKey & 0x02) ? 2 : 1;
|
||||
+ // return result | ((result_size_ == 1) ? 0 : 2);
|
||||
+ SaveFPRegsMode save_doubles = (MinorKey & 0x01) ? kSaveFPRegs : kDontSaveFPRegs;
|
||||
+ CEntryStub stub(isolate, result_size, save_doubles);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case CallConstruct: {
|
||||
+ // int MinorKey() const { return flags_; }
|
||||
+ CallConstructorFlags flags = (CallConstructorFlags) MinorKey;
|
||||
+ CallConstructStub stub(isolate, flags);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case FastNewContext: {
|
||||
+ // int NotMissMinorKey() const V8_OVERRIDE { return slots_; }
|
||||
+ int slots = MinorKey;
|
||||
+ FastNewContextStub stub(isolate, slots);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case FastNewClosure: {
|
||||
+ // class StrictModeBits: public BitField<bool, 0, 1> {};
|
||||
+ StrictMode strict_mode = (StrictMode) (MinorKey & 0x01);
|
||||
+ // class IsGeneratorBits: public BitField<bool, 1, 1> {};
|
||||
+ bool is_generator = MinorKey & 0x02;
|
||||
+ FastNewClosureStub stub(isolate, strict_mode, is_generator);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case RecordWrite: {
|
||||
+ #if V8_TARGET_ARCH_IA32
|
||||
+ // class ObjectBits: public BitField<int, 0, 3> {};
|
||||
+ Register object = Register::from_code(MinorKey & 0x07);
|
||||
+ // class ValueBits: public BitField<int, 3, 3> {};
|
||||
+ Register value = Register::from_code((MinorKey >> 3) & 0x07);
|
||||
+ // class AddressBits: public BitField<int, 6, 3> {};
|
||||
+ Register address = Register::from_code((MinorKey >> 6) & 0x07);
|
||||
+ // class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {};
|
||||
+ RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 9) & 0x01);
|
||||
+ // class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 10, 1> {};
|
||||
+ SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 10) & 0x01);
|
||||
+ RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode);
|
||||
+ #endif
|
||||
+ #if V8_TARGET_ARCH_X64
|
||||
+ // class ObjectBits: public BitField<int, 0, 4> {};
|
||||
+ Register object = Register::from_code(MinorKey & 0x0F);
|
||||
+ // class ValueBits: public BitField<int, 4, 4> {};
|
||||
+ Register value = Register::from_code((MinorKey >> 4) & 0x0F);
|
||||
+ // class AddressBits: public BitField<int, 8, 4> {};
|
||||
+ Register address = Register::from_code((MinorKey >> 8) & 0x0F);
|
||||
+ // class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
|
||||
+ RememberedSetAction remembered_set_action = (RememberedSetAction) ((MinorKey >> 12) & 0x01);
|
||||
+ // class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
|
||||
+ SaveFPRegsMode fp_mode = (SaveFPRegsMode) ((MinorKey >> 13) & 0x01);
|
||||
+ RecordWriteStub stub(isolate, object, value, address, remembered_set_action, fp_mode);
|
||||
+ #endif
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case ToNumber: {
|
||||
+ ToNumberStub stub(isolate);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case ArgumentsAccess: {
|
||||
+ // int MinorKey() const { return type_; }
|
||||
+ ArgumentsAccessStub::Type type = (ArgumentsAccessStub::Type) MinorKey;
|
||||
+ ArgumentsAccessStub stub(isolate, type);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case FastCloneShallowArray: {
|
||||
+ // class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
|
||||
+ AllocationSiteMode allocation_site_mode = (AllocationSiteMode) (MinorKey & 0x01);
|
||||
+ FastCloneShallowArrayStub stub(isolate, allocation_site_mode);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case StoreArrayLiteralElement: {
|
||||
+ StoreArrayLiteralElementStub stub(isolate);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case CallFunction: {
|
||||
+ // class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
|
||||
+ CallFunctionFlags flags = (CallFunctionFlags) (MinorKey & 0x03);
|
||||
+ // class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
|
||||
+ unsigned argc = MinorKey >> 2;
|
||||
+ CallFunctionStub stub(isolate, argc, flags);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case Instanceof: {
|
||||
+ // int MinorKey() const { return static_cast<int>(flags_); }
|
||||
+ InstanceofStub::Flags flags = (InstanceofStub::Flags) MinorKey;
|
||||
+ InstanceofStub stub(isolate, flags);
|
||||
+ CodeStub* pstub = &stub;
|
||||
+ CheckCodeStub(pstub, MajorKey, MinorKey);
|
||||
+ call(pstub, value_out);
|
||||
+ break;
|
||||
+ }
|
||||
+ case NUMBER_OF_IDS:
|
||||
+ UNREACHABLE();
|
||||
+ case NoCache:
|
||||
+ *value_out = NULL;
|
||||
+ break;
|
||||
+ default: {
|
||||
+ fprintf(stderr, "unhandled MajorKey: %s (%d)\n", MajorName(MajorKey, false), MajorKey);
|
||||
+ UNREACHABLE();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
|
||||
+ Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
|
||||
+ // Code stubs with special cache cannot be recreated from stub key.
|
||||
+ *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
|
||||
+}
|
||||
+
|
||||
+
|
||||
+MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
|
||||
+ HandleScope scope(isolate);
|
||||
+ Handle<Code> code;
|
||||
+ void** value_out = reinterpret_cast<void**>(&code);
|
||||
+ Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
|
||||
+ return scope.CloseAndEscape(code);
|
||||
+}
|
||||
+
|
||||
+
|
||||
// static
|
||||
void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
|
||||
// Generate the uninitialized versions of the stub.
|
||||
diff --git a/src/code-stubs.h b/src/code-stubs.h
|
||||
index c1d051b..9cc12df 100644
|
||||
--- node/deps/v8/src/code-stubs.h
|
||||
+++ node/deps/v8/src/code-stubs.h
|
||||
@@ -179,6 +179,8 @@ class CodeStub BASE_EMBEDDED {
|
||||
// Lookup the code in the (possibly custom) cache.
|
||||
bool FindCodeInCache(Code** code_out);
|
||||
|
||||
+ static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
|
||||
+
|
||||
// Returns information for computing the number key.
|
||||
virtual Major MajorKey() const = 0;
|
||||
virtual int MinorKey() const = 0;
|
||||
@@ -242,6 +244,14 @@ class CodeStub BASE_EMBEDDED {
|
||||
// If a stub uses a special cache override this.
|
||||
virtual bool UseSpecialCache() { return false; }
|
||||
|
||||
+ // We use this dispatch to statically instantiate the correct code stub for
|
||||
+ // the given stub key and call the passed function with that code stub.
|
||||
+ typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
|
||||
+ static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
|
||||
+ DispatchedCall call);
|
||||
+
|
||||
+ static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
|
||||
+
|
||||
STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
|
||||
class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
|
||||
class MinorKeyBits: public BitField<uint32_t,
|
||||
+484
@@ -0,0 +1,484 @@
|
||||
commit a49ac519c8df83c52ed67e3860c51ccad80e037a
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Wed Sep 17 12:50:17 2014 +0000
|
||||
|
||||
Serialize code stubs using stub key.
|
||||
|
||||
Also add some tracing to the code serializer.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/556243005
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24002 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
|
||||
index 4208e62..792fda9 100644
|
||||
--- node/deps/v8/src/flag-definitions.h
|
||||
+++ node/deps/v8/src/flag-definitions.h
|
||||
@@ -428,6 +428,7 @@ DEFINE_BOOL(trace_stub_failures, false,
|
||||
"trace deoptimization of generated code stubs")
|
||||
|
||||
DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
|
||||
+DEFINE_BOOL(trace_code_serializer, false, "trace code serializer")
|
||||
|
||||
// compiler.cc
|
||||
DEFINE_INT(min_preparse_length, 1024,
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 1a19ab0..9447fc8 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "src/api.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/bootstrapper.h"
|
||||
+#include "src/code-stubs.h"
|
||||
#include "src/deoptimizer.h"
|
||||
#include "src/execution.h"
|
||||
#include "src/global-handles.h"
|
||||
@@ -872,7 +873,7 @@ void Deserializer::ReadChunk(Object** current,
|
||||
} else if (where == kAttachedReference) { \
|
||||
DCHECK(deserializing_user_code()); \
|
||||
int index = source_->GetInt(); \
|
||||
- new_object = attached_objects_->at(index); \
|
||||
+ new_object = *attached_objects_->at(index); \
|
||||
emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
|
||||
} else { \
|
||||
DCHECK(where == kBackrefWithSkip); \
|
||||
@@ -1125,6 +1126,10 @@ void Deserializer::ReadChunk(Object** current,
|
||||
// the current object.
|
||||
CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0)
|
||||
CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0)
|
||||
+ CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0)
|
||||
+ CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0)
|
||||
+ CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0)
|
||||
+ CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0)
|
||||
|
||||
#undef CASE_STATEMENT
|
||||
#undef CASE_BODY
|
||||
@@ -1311,12 +1316,12 @@ int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
|
||||
// location into a later object. We can encode the location as an offset from
|
||||
// the start of the deserialized objects or as an offset backwards from the
|
||||
// current allocation pointer.
|
||||
-void Serializer::SerializeReferenceToPreviousObject(
|
||||
- int space,
|
||||
- int address,
|
||||
- HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point,
|
||||
- int skip) {
|
||||
+void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
|
||||
+ HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point,
|
||||
+ int skip) {
|
||||
+ int space = SpaceOfObject(heap_object);
|
||||
+ int address = address_mapper_.MappedTo(heap_object);
|
||||
int offset = CurrentAllocationAddress(space) - address;
|
||||
// Shift out the bits that are always 0.
|
||||
offset >>= kObjectAlignmentBits;
|
||||
@@ -1347,12 +1352,7 @@ void StartupSerializer::SerializeObject(
|
||||
}
|
||||
|
||||
if (address_mapper_.IsMapped(heap_object)) {
|
||||
- int space = SpaceOfObject(heap_object);
|
||||
- int address = address_mapper_.MappedTo(heap_object);
|
||||
- SerializeReferenceToPreviousObject(space,
|
||||
- address,
|
||||
- how_to_code,
|
||||
- where_to_point,
|
||||
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
||||
skip);
|
||||
} else {
|
||||
if (skip != 0) {
|
||||
@@ -1455,12 +1455,7 @@ void PartialSerializer::SerializeObject(
|
||||
DCHECK(!heap_object->IsInternalizedString());
|
||||
|
||||
if (address_mapper_.IsMapped(heap_object)) {
|
||||
- int space = SpaceOfObject(heap_object);
|
||||
- int address = address_mapper_.MappedTo(heap_object);
|
||||
- SerializeReferenceToPreviousObject(space,
|
||||
- address,
|
||||
- how_to_code,
|
||||
- where_to_point,
|
||||
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
||||
skip);
|
||||
} else {
|
||||
if (skip != 0) {
|
||||
@@ -1782,17 +1777,32 @@ void Serializer::InitializeCodeAddressMap() {
|
||||
ScriptData* CodeSerializer::Serialize(Isolate* isolate,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<String> source) {
|
||||
+ base::ElapsedTimer timer;
|
||||
+ if (FLAG_profile_deserialization) timer.Start();
|
||||
+
|
||||
// Serialize code object.
|
||||
List<byte> payload;
|
||||
ListSnapshotSink list_sink(&payload);
|
||||
- CodeSerializer cs(isolate, &list_sink, *source);
|
||||
+ DebugSnapshotSink debug_sink(&list_sink);
|
||||
+ SnapshotByteSink* sink = FLAG_trace_code_serializer
|
||||
+ ? static_cast<SnapshotByteSink*>(&debug_sink)
|
||||
+ : static_cast<SnapshotByteSink*>(&list_sink);
|
||||
+ CodeSerializer cs(isolate, sink, *source);
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object** location = Handle<Object>::cast(info).location();
|
||||
cs.VisitPointer(location);
|
||||
cs.Pad();
|
||||
|
||||
SerializedCodeData data(&payload, &cs);
|
||||
- return data.GetScriptData();
|
||||
+ ScriptData* script_data = data.GetScriptData();
|
||||
+
|
||||
+ if (FLAG_profile_deserialization) {
|
||||
+ double ms = timer.Elapsed().InMillisecondsF();
|
||||
+ int length = script_data->length();
|
||||
+ PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms);
|
||||
+ }
|
||||
+
|
||||
+ return script_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -1813,16 +1823,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
return;
|
||||
}
|
||||
|
||||
- // TODO(yangguo) wire up stubs from stub cache.
|
||||
// TODO(yangguo) wire up global object.
|
||||
// TODO(yangguo) We cannot deal with different hash seeds yet.
|
||||
DCHECK(!heap_object->IsHashTable());
|
||||
|
||||
if (address_mapper_.IsMapped(heap_object)) {
|
||||
- int space = SpaceOfObject(heap_object);
|
||||
- int address = address_mapper_.MappedTo(heap_object);
|
||||
- SerializeReferenceToPreviousObject(space, address, how_to_code,
|
||||
- where_to_point, skip);
|
||||
+ SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
||||
+ skip);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1832,7 +1839,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
||||
return;
|
||||
}
|
||||
- // TODO(yangguo) figure out whether other code kinds can be handled smarter.
|
||||
+ if (code_object->IsCodeStubOrIC()) {
|
||||
+ SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
||||
+ return;
|
||||
+ }
|
||||
+ code_object->ClearInlineCaches();
|
||||
}
|
||||
|
||||
if (heap_object == source_) {
|
||||
@@ -1840,6 +1851,14 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
return;
|
||||
}
|
||||
|
||||
+ SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
||||
+ HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point,
|
||||
+ int skip) {
|
||||
if (heap_object->IsScript()) {
|
||||
// The wrapper cache uses a Foreign object to point to a global handle.
|
||||
// However, the object visitor expects foreign objects to point to external
|
||||
@@ -1851,6 +1870,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
sink_->Put(kSkip, "SkipFromSerializeObject");
|
||||
sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
|
||||
}
|
||||
+
|
||||
+ if (FLAG_trace_code_serializer) {
|
||||
+ PrintF("Encoding heap object: ");
|
||||
+ heap_object->ShortPrint();
|
||||
+ PrintF("\n");
|
||||
+ }
|
||||
+
|
||||
// Object has not yet been serialized. Serialize it here.
|
||||
ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
|
||||
where_to_point);
|
||||
@@ -1870,11 +1896,62 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
int builtin_index = builtin->builtin_index();
|
||||
DCHECK_LT(builtin_index, Builtins::builtin_count);
|
||||
DCHECK_LE(0, builtin_index);
|
||||
+
|
||||
+ if (FLAG_trace_code_serializer) {
|
||||
+ PrintF("Encoding builtin: %s\n",
|
||||
+ isolate()->builtins()->name(builtin_index));
|
||||
+ }
|
||||
+
|
||||
sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
|
||||
sink_->PutInt(builtin_index, "builtin_index");
|
||||
}
|
||||
|
||||
|
||||
+void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point, int skip) {
|
||||
+ DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
|
||||
+ (how_to_code == kPlain && where_to_point == kInnerPointer) ||
|
||||
+ (how_to_code == kFromCode && where_to_point == kInnerPointer));
|
||||
+ uint32_t stub_key = code->stub_key();
|
||||
+
|
||||
+ if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) {
|
||||
+ if (FLAG_trace_code_serializer) {
|
||||
+ PrintF("Encoding uncacheable code stub as heap object\n");
|
||||
+ }
|
||||
+ SerializeHeapObject(code, how_to_code, where_to_point, skip);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (skip != 0) {
|
||||
+ sink_->Put(kSkip, "SkipFromSerializeCodeStub");
|
||||
+ sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
|
||||
+ }
|
||||
+
|
||||
+ int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
|
||||
+
|
||||
+ if (FLAG_trace_code_serializer) {
|
||||
+ PrintF("Encoding code stub %s as %d\n",
|
||||
+ CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false),
|
||||
+ index);
|
||||
+ }
|
||||
+
|
||||
+ sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub");
|
||||
+ sink_->PutInt(index, "CodeStub key");
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
|
||||
+ // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2).
|
||||
+ int index = 0;
|
||||
+ while (index < stub_keys_.length()) {
|
||||
+ if (stub_keys_[index] == stub_key) return index;
|
||||
+ index++;
|
||||
+ }
|
||||
+ stub_keys_.Add(stub_key);
|
||||
+ return index;
|
||||
+}
|
||||
+
|
||||
+
|
||||
void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
|
||||
WhereToPoint where_to_point,
|
||||
int skip) {
|
||||
@@ -1883,6 +1960,10 @@ void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
|
||||
sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
|
||||
}
|
||||
|
||||
+ if (FLAG_trace_code_serializer) {
|
||||
+ PrintF("Encoding source object\n");
|
||||
+ }
|
||||
+
|
||||
DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
|
||||
sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
|
||||
sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex");
|
||||
@@ -1894,22 +1975,36 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
|
||||
Handle<String> source) {
|
||||
base::ElapsedTimer timer;
|
||||
if (FLAG_profile_deserialization) timer.Start();
|
||||
- SerializedCodeData scd(data, *source);
|
||||
- SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
||||
- Deserializer deserializer(&payload);
|
||||
- STATIC_ASSERT(NEW_SPACE == 0);
|
||||
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
||||
- deserializer.set_reservation(i, scd.GetReservation(i));
|
||||
- }
|
||||
-
|
||||
- // Prepare and register list of attached objects.
|
||||
- Vector<Object*> attached_objects = Vector<Object*>::New(1);
|
||||
- attached_objects[kSourceObjectIndex] = *source;
|
||||
- deserializer.SetAttachedObjects(&attached_objects);
|
||||
|
||||
Object* root;
|
||||
- deserializer.DeserializePartial(isolate, &root);
|
||||
- deserializer.FlushICacheForNewCodeObjects();
|
||||
+
|
||||
+ {
|
||||
+ HandleScope scope(isolate);
|
||||
+
|
||||
+ SerializedCodeData scd(data, *source);
|
||||
+ SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
||||
+ Deserializer deserializer(&payload);
|
||||
+ STATIC_ASSERT(NEW_SPACE == 0);
|
||||
+ for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
||||
+ deserializer.set_reservation(i, scd.GetReservation(i));
|
||||
+ }
|
||||
+
|
||||
+ // Prepare and register list of attached objects.
|
||||
+ Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys();
|
||||
+ Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
|
||||
+ code_stub_keys.length() + kCodeStubsBaseIndex);
|
||||
+ attached_objects[kSourceObjectIndex] = source;
|
||||
+ for (int i = 0; i < code_stub_keys.length(); i++) {
|
||||
+ attached_objects[i + kCodeStubsBaseIndex] =
|
||||
+ CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
|
||||
+ }
|
||||
+ deserializer.SetAttachedObjects(&attached_objects);
|
||||
+
|
||||
+ // Deserialize.
|
||||
+ deserializer.DeserializePartial(isolate, &root);
|
||||
+ deserializer.FlushICacheForNewCodeObjects();
|
||||
+ }
|
||||
+
|
||||
if (FLAG_profile_deserialization) {
|
||||
double ms = timer.Elapsed().InMillisecondsF();
|
||||
int length = data->length();
|
||||
@@ -1922,18 +2017,35 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
|
||||
SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
||||
: owns_script_data_(true) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
- int data_length = payload->length() + kHeaderEntries * kIntSize;
|
||||
+ List<uint32_t>* stub_keys = cs->stub_keys();
|
||||
+
|
||||
+ // Calculate sizes.
|
||||
+ int num_stub_keys = stub_keys->length();
|
||||
+ int stub_keys_size = stub_keys->length() * kInt32Size;
|
||||
+ int data_length = kHeaderSize + stub_keys_size + payload->length();
|
||||
+
|
||||
+ // Allocate backing store and create result data.
|
||||
byte* data = NewArray<byte>(data_length);
|
||||
DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
|
||||
- CopyBytes(data + kHeaderEntries * kIntSize, payload->begin(),
|
||||
- static_cast<size_t>(payload->length()));
|
||||
script_data_ = new ScriptData(data, data_length);
|
||||
script_data_->AcquireDataOwnership();
|
||||
+
|
||||
+ // Set header values.
|
||||
SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
|
||||
+ SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
|
||||
+ SetHeaderValue(kPayloadLengthOffset, payload->length());
|
||||
STATIC_ASSERT(NEW_SPACE == 0);
|
||||
for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
||||
SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
|
||||
}
|
||||
+
|
||||
+ // Copy code stub keys.
|
||||
+ CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()),
|
||||
+ stub_keys_size);
|
||||
+
|
||||
+ // Copy serialized data.
|
||||
+ CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(),
|
||||
+ static_cast<size_t>(payload->length()));
|
||||
}
|
||||
|
||||
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 066d75f..71b274b 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -257,7 +257,7 @@ class Deserializer: public SerializerDeserializer {
|
||||
|
||||
// Serialized user code reference certain objects that are provided in a list
|
||||
// By calling this method, we assume that we are deserializing user code.
|
||||
- void SetAttachedObjects(Vector<Object*>* attached_objects) {
|
||||
+ void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
|
||||
attached_objects_ = attached_objects;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ class Deserializer: public SerializerDeserializer {
|
||||
Isolate* isolate_;
|
||||
|
||||
// Objects from the attached object descriptions in the serialized user code.
|
||||
- Vector<Object*>* attached_objects_;
|
||||
+ Vector<Handle<Object> >* attached_objects_;
|
||||
|
||||
SnapshotByteSource* source_;
|
||||
// This is the address of the next object that will be allocated in each
|
||||
@@ -459,12 +459,10 @@ class Serializer : public SerializerDeserializer {
|
||||
HowToCode how_to_code,
|
||||
WhereToPoint where_to_point,
|
||||
int skip) = 0;
|
||||
- void SerializeReferenceToPreviousObject(
|
||||
- int space,
|
||||
- int address,
|
||||
- HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point,
|
||||
- int skip);
|
||||
+ void SerializeReferenceToPreviousObject(HeapObject* heap_object,
|
||||
+ HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point,
|
||||
+ int skip);
|
||||
void InitializeAllocators();
|
||||
// This will return the space for an object.
|
||||
static int SpaceOfObject(HeapObject* object);
|
||||
@@ -594,20 +592,29 @@ class CodeSerializer : public Serializer {
|
||||
Handle<String> source);
|
||||
|
||||
static const int kSourceObjectIndex = 0;
|
||||
+ static const int kCodeStubsBaseIndex = 1;
|
||||
|
||||
String* source() {
|
||||
DCHECK(!AllowHeapAllocation::IsAllowed());
|
||||
return source_;
|
||||
}
|
||||
|
||||
+ List<uint32_t>* stub_keys() { return &stub_keys_; }
|
||||
+
|
||||
private:
|
||||
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip);
|
||||
+ void SerializeCodeStub(Code* code, HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point, int skip);
|
||||
void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
|
||||
int skip);
|
||||
+ void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point, int skip);
|
||||
+ int AddCodeStubKey(uint32_t stub_key);
|
||||
|
||||
DisallowHeapAllocation no_gc_;
|
||||
String* source_;
|
||||
+ List<uint32_t> stub_keys_;
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
|
||||
};
|
||||
|
||||
@@ -638,12 +645,22 @@ class SerializedCodeData {
|
||||
return result;
|
||||
}
|
||||
|
||||
+ Vector<const uint32_t> CodeStubKeys() const {
|
||||
+ return Vector<const uint32_t>(
|
||||
+ reinterpret_cast<const uint32_t*>(script_data_->data() + kHeaderSize),
|
||||
+ GetHeaderValue(kNumCodeStubKeysOffset));
|
||||
+ }
|
||||
+
|
||||
const byte* Payload() const {
|
||||
- return script_data_->data() + kHeaderEntries * kIntSize;
|
||||
+ int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
|
||||
+ return script_data_->data() + kHeaderSize + code_stubs_size;
|
||||
}
|
||||
|
||||
int PayloadLength() const {
|
||||
- return script_data_->length() - kHeaderEntries * kIntSize;
|
||||
+ int payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
+ DCHECK_EQ(script_data_->data() + script_data_->length(),
|
||||
+ Payload() + payload_length);
|
||||
+ return payload_length;
|
||||
}
|
||||
|
||||
int GetReservation(int space) const {
|
||||
@@ -666,10 +683,21 @@ class SerializedCodeData {
|
||||
|
||||
// The data header consists of int-sized entries:
|
||||
// [0] version hash
|
||||
- // [1..7] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
|
||||
+ // [1] number of code stub keys
|
||||
+ // [2] payload length
|
||||
+ // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
|
||||
static const int kCheckSumOffset = 0;
|
||||
- static const int kReservationsOffset = 1;
|
||||
- static const int kHeaderEntries = 8;
|
||||
+ static const int kNumCodeStubKeysOffset = 1;
|
||||
+ static const int kPayloadLengthOffset = 2;
|
||||
+ static const int kReservationsOffset = 3;
|
||||
+
|
||||
+ static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
|
||||
+ static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
|
||||
+ static const int kHeaderSize = kHeaderEntries * kIntSize;
|
||||
+
|
||||
+ // Following the header, we store, in sequential order
|
||||
+ // - code stub keys
|
||||
+ // - serialization payload
|
||||
|
||||
ScriptData* script_data_;
|
||||
bool owns_script_data_;
|
||||
+739
@@ -0,0 +1,739 @@
|
||||
commit 1257f35c21c9aeb054ae57a0087c50d91f625c24
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Thu Sep 25 07:32:13 2014 +0000
|
||||
|
||||
Support large objects in the serializer/deserializer.
|
||||
|
||||
R=hpayer@chromium.org, mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/581223004
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24204 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
||||
index 3d0c2f0..78c45b0 100644
|
||||
--- node/deps/v8/src/heap/heap.cc
|
||||
+++ node/deps/v8/src/heap/heap.cc
|
||||
@@ -923,9 +923,12 @@ void Heap::ReserveSpace(int* sizes, Address* locations_out) {
|
||||
static const int kThreshold = 20;
|
||||
while (gc_performed && counter++ < kThreshold) {
|
||||
gc_performed = false;
|
||||
- DCHECK(NEW_SPACE == FIRST_PAGED_SPACE - 1);
|
||||
- for (int space = NEW_SPACE; space <= LAST_PAGED_SPACE; space++) {
|
||||
- if (sizes[space] != 0) {
|
||||
+ for (int space = NEW_SPACE; space < Serializer::kNumberOfSpaces; space++) {
|
||||
+ if (sizes[space] == 0) continue;
|
||||
+ bool perform_gc = false;
|
||||
+ if (space == LO_SPACE) {
|
||||
+ perform_gc = !lo_space()->CanAllocateSize(sizes[space]);
|
||||
+ } else {
|
||||
AllocationResult allocation;
|
||||
if (space == NEW_SPACE) {
|
||||
allocation = new_space()->AllocateRaw(sizes[space]);
|
||||
@@ -933,23 +936,27 @@ void Heap::ReserveSpace(int* sizes, Address* locations_out) {
|
||||
allocation = paged_space(space)->AllocateRaw(sizes[space]);
|
||||
}
|
||||
FreeListNode* node;
|
||||
- if (!allocation.To(&node)) {
|
||||
- if (space == NEW_SPACE) {
|
||||
- Heap::CollectGarbage(NEW_SPACE,
|
||||
- "failed to reserve space in the new space");
|
||||
- } else {
|
||||
- AbortIncrementalMarkingAndCollectGarbage(
|
||||
- this, static_cast<AllocationSpace>(space),
|
||||
- "failed to reserve space in paged space");
|
||||
- }
|
||||
- gc_performed = true;
|
||||
- break;
|
||||
- } else {
|
||||
+ if (allocation.To(&node)) {
|
||||
// Mark with a free list node, in case we have a GC before
|
||||
// deserializing.
|
||||
node->set_size(this, sizes[space]);
|
||||
+ DCHECK(space < Serializer::kNumberOfPreallocatedSpaces);
|
||||
locations_out[space] = node->address();
|
||||
+ } else {
|
||||
+ perform_gc = true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (perform_gc) {
|
||||
+ if (space == NEW_SPACE) {
|
||||
+ Heap::CollectGarbage(NEW_SPACE,
|
||||
+ "failed to reserve space in the new space");
|
||||
+ } else {
|
||||
+ AbortIncrementalMarkingAndCollectGarbage(
|
||||
+ this, static_cast<AllocationSpace>(space),
|
||||
+ "failed to reserve space in paged or large object space");
|
||||
}
|
||||
+ gc_performed = true;
|
||||
+ break; // Abort for-loop over spaces and retry.
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/heap/heap.h b/src/heap/heap.h
|
||||
index 956b859..87b939a 100644
|
||||
--- node/deps/v8/src/heap/heap.h
|
||||
+++ node/deps/v8/src/heap/heap.h
|
||||
@@ -2021,6 +2021,7 @@ class Heap {
|
||||
int gc_callbacks_depth_;
|
||||
|
||||
friend class AlwaysAllocateScope;
|
||||
+ friend class Deserializer;
|
||||
friend class Factory;
|
||||
friend class GCCallbacksScope;
|
||||
friend class GCTracer;
|
||||
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
|
||||
index f8d340f..ae4048f 100644
|
||||
--- node/deps/v8/src/heap/spaces.cc
|
||||
+++ node/deps/v8/src/heap/spaces.cc
|
||||
@@ -2840,9 +2840,7 @@ AllocationResult LargeObjectSpace::AllocateRaw(int object_size,
|
||||
return AllocationResult::Retry(identity());
|
||||
}
|
||||
|
||||
- if (Size() + object_size > max_capacity_) {
|
||||
- return AllocationResult::Retry(identity());
|
||||
- }
|
||||
+ if (!CanAllocateSize(object_size)) return AllocationResult::Retry(identity());
|
||||
|
||||
LargePage* page = heap()->isolate()->memory_allocator()->AllocateLargePage(
|
||||
object_size, this, executable);
|
||||
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
|
||||
index 9ecb3c4..1a89449 100644
|
||||
--- node/deps/v8/src/heap/spaces.h
|
||||
+++ node/deps/v8/src/heap/spaces.h
|
||||
@@ -2728,6 +2728,8 @@ class LargeObjectSpace : public Space {
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocateRaw(int object_size, Executability executable);
|
||||
|
||||
+ bool CanAllocateSize(int size) { return Size() + size <= max_capacity_; }
|
||||
+
|
||||
// Available bytes for objects in this space.
|
||||
inline intptr_t Available();
|
||||
|
||||
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
|
||||
index b4a4018..eacd098 100644
|
||||
--- node/deps/v8/src/mksnapshot.cc
|
||||
+++ node/deps/v8/src/mksnapshot.cc
|
||||
@@ -84,10 +84,10 @@ class SnapshotWriter {
|
||||
i::List<i::byte> startup_blob;
|
||||
i::ListSnapshotSink sink(&startup_blob);
|
||||
|
||||
- int spaces[] = {
|
||||
- i::NEW_SPACE, i::OLD_POINTER_SPACE, i::OLD_DATA_SPACE, i::CODE_SPACE,
|
||||
- i::MAP_SPACE, i::CELL_SPACE, i::PROPERTY_CELL_SPACE
|
||||
- };
|
||||
+ int spaces[] = {i::NEW_SPACE, i::OLD_POINTER_SPACE,
|
||||
+ i::OLD_DATA_SPACE, i::CODE_SPACE,
|
||||
+ i::MAP_SPACE, i::CELL_SPACE,
|
||||
+ i::PROPERTY_CELL_SPACE, i::LO_SPACE};
|
||||
|
||||
i::byte* snapshot_bytes = snapshot_data.begin();
|
||||
sink.PutBlob(snapshot_bytes, snapshot_data.length(), "snapshot");
|
||||
@@ -197,6 +197,7 @@ class SnapshotWriter {
|
||||
WriteSizeVar(ser, prefix, "map", i::MAP_SPACE);
|
||||
WriteSizeVar(ser, prefix, "cell", i::CELL_SPACE);
|
||||
WriteSizeVar(ser, prefix, "property_cell", i::PROPERTY_CELL_SPACE);
|
||||
+ WriteSizeVar(ser, prefix, "lo", i::LO_SPACE);
|
||||
fprintf(fp_, "\n");
|
||||
}
|
||||
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 843f976..894a1be 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -596,8 +596,9 @@ Deserializer::Deserializer(SnapshotByteSource* source)
|
||||
: isolate_(NULL),
|
||||
attached_objects_(NULL),
|
||||
source_(source),
|
||||
- external_reference_decoder_(NULL) {
|
||||
- for (int i = 0; i < LAST_SPACE + 1; i++) {
|
||||
+ external_reference_decoder_(NULL),
|
||||
+ deserialized_large_objects_(0) {
|
||||
+ for (int i = 0; i < kNumberOfSpaces; i++) {
|
||||
reservations_[i] = kUninitializedReservation;
|
||||
}
|
||||
}
|
||||
@@ -615,7 +616,7 @@ void Deserializer::FlushICacheForNewCodeObjects() {
|
||||
void Deserializer::Deserialize(Isolate* isolate) {
|
||||
isolate_ = isolate;
|
||||
DCHECK(isolate_ != NULL);
|
||||
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
|
||||
+ isolate_->heap()->ReserveSpace(reservations_, high_water_);
|
||||
// No active threads.
|
||||
DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
|
||||
// No active handles.
|
||||
@@ -662,7 +663,8 @@ void Deserializer::DeserializePartial(Isolate* isolate, Object** root) {
|
||||
for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
|
||||
DCHECK(reservations_[i] != kUninitializedReservation);
|
||||
}
|
||||
- isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
|
||||
+ Heap* heap = isolate->heap();
|
||||
+ heap->ReserveSpace(reservations_, high_water_);
|
||||
if (external_reference_decoder_ == NULL) {
|
||||
external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
|
||||
}
|
||||
@@ -798,11 +800,40 @@ void Deserializer::ReadObject(int space_number,
|
||||
|
||||
*write_back = obj;
|
||||
#ifdef DEBUG
|
||||
- bool is_codespace = (space_number == CODE_SPACE);
|
||||
- DCHECK(obj->IsCode() == is_codespace);
|
||||
+ if (obj->IsCode()) {
|
||||
+ DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
|
||||
+ } else {
|
||||
+ DCHECK(space_number != CODE_SPACE);
|
||||
+ }
|
||||
#endif
|
||||
}
|
||||
|
||||
+
|
||||
+// We know the space requirements before deserialization and can
|
||||
+// pre-allocate that reserved space. During deserialization, all we need
|
||||
+// to do is to bump up the pointer for each space in the reserved
|
||||
+// space. This is also used for fixing back references.
|
||||
+// Since multiple large objects cannot be folded into one large object
|
||||
+// space allocation, we have to do an actual allocation when deserializing
|
||||
+// each large object. Instead of tracking offset for back references, we
|
||||
+// reference large objects by index.
|
||||
+Address Deserializer::Allocate(int space_index, int size) {
|
||||
+ if (space_index == LO_SPACE) {
|
||||
+ AlwaysAllocateScope scope(isolate_);
|
||||
+ LargeObjectSpace* lo_space = isolate_->heap()->lo_space();
|
||||
+ Executability exec = static_cast<Executability>(source_->GetInt());
|
||||
+ AllocationResult result = lo_space->AllocateRaw(size, exec);
|
||||
+ HeapObject* obj = HeapObject::cast(result.ToObjectChecked());
|
||||
+ deserialized_large_objects_.Add(obj);
|
||||
+ return obj->address();
|
||||
+ } else {
|
||||
+ DCHECK(space_index < kNumberOfPreallocatedSpaces);
|
||||
+ Address address = high_water_[space_index];
|
||||
+ high_water_[space_index] = address + size;
|
||||
+ return address;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void Deserializer::ReadChunk(Object** current,
|
||||
Object** limit,
|
||||
int source_space,
|
||||
@@ -925,15 +956,16 @@ void Deserializer::ReadChunk(Object** current,
|
||||
// This generates a case and a body for the new space (which has to do extra
|
||||
// write barrier handling) and handles the other spaces with 8 fall-through
|
||||
// cases and one body.
|
||||
-#define ALL_SPACES(where, how, within) \
|
||||
- CASE_STATEMENT(where, how, within, NEW_SPACE) \
|
||||
- CASE_BODY(where, how, within, NEW_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, CODE_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, CELL_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \
|
||||
- CASE_STATEMENT(where, how, within, MAP_SPACE) \
|
||||
+#define ALL_SPACES(where, how, within) \
|
||||
+ CASE_STATEMENT(where, how, within, NEW_SPACE) \
|
||||
+ CASE_BODY(where, how, within, NEW_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, CODE_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, MAP_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, CELL_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \
|
||||
+ CASE_STATEMENT(where, how, within, LO_SPACE) \
|
||||
CASE_BODY(where, how, within, kAnyOldSpace)
|
||||
|
||||
#define FOUR_CASES(byte_code) \
|
||||
@@ -1184,12 +1216,11 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
|
||||
sink_(sink),
|
||||
external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
|
||||
root_index_wave_front_(0),
|
||||
- code_address_map_(NULL) {
|
||||
+ code_address_map_(NULL),
|
||||
+ seen_large_objects_index_(0) {
|
||||
// The serializer is meant to be used only to generate initial heap images
|
||||
// from a context in which there is only one isolate.
|
||||
- for (int i = 0; i <= LAST_SPACE; i++) {
|
||||
- fullness_[i] = 0;
|
||||
- }
|
||||
+ for (int i = 0; i < kNumberOfSpaces; i++) fullness_[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1324,10 +1355,7 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
|
||||
WhereToPoint where_to_point,
|
||||
int skip) {
|
||||
int space = SpaceOfObject(heap_object);
|
||||
- int address = address_mapper_.MappedTo(heap_object);
|
||||
- int offset = CurrentAllocationAddress(space) - address;
|
||||
- // Shift out the bits that are always 0.
|
||||
- offset >>= kObjectAlignmentBits;
|
||||
+
|
||||
if (skip == 0) {
|
||||
sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
|
||||
} else {
|
||||
@@ -1335,7 +1363,17 @@ void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
|
||||
"BackRefSerWithSkip");
|
||||
sink_->PutInt(skip, "BackRefSkipDistance");
|
||||
}
|
||||
- sink_->PutInt(offset, "offset");
|
||||
+
|
||||
+ if (space == LO_SPACE) {
|
||||
+ int index = address_mapper_.MappedTo(heap_object);
|
||||
+ sink_->PutInt(index, "large object index");
|
||||
+ } else {
|
||||
+ int address = address_mapper_.MappedTo(heap_object);
|
||||
+ int offset = CurrentAllocationAddress(space) - address;
|
||||
+ // Shift out the bits that are always 0.
|
||||
+ offset >>= kObjectAlignmentBits;
|
||||
+ sink_->PutInt(offset, "offset");
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -1494,8 +1532,18 @@ void Serializer::ObjectSerializer::Serialize() {
|
||||
}
|
||||
|
||||
// Mark this object as already serialized.
|
||||
- int offset = serializer_->Allocate(space, size);
|
||||
- serializer_->address_mapper()->AddMapping(object_, offset);
|
||||
+ if (space == LO_SPACE) {
|
||||
+ if (object_->IsCode()) {
|
||||
+ sink_->PutInt(EXECUTABLE, "executable large object");
|
||||
+ } else {
|
||||
+ sink_->PutInt(NOT_EXECUTABLE, "not executable large object");
|
||||
+ }
|
||||
+ int index = serializer_->AllocateLargeObject(size);
|
||||
+ serializer_->address_mapper()->AddMapping(object_, index);
|
||||
+ } else {
|
||||
+ int offset = serializer_->Allocate(space, size);
|
||||
+ serializer_->address_mapper()->AddMapping(object_, offset);
|
||||
+ }
|
||||
|
||||
// Serialize the map (first word of the object).
|
||||
serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject, 0);
|
||||
@@ -1747,8 +1795,14 @@ int Serializer::SpaceOfObject(HeapObject* object) {
|
||||
}
|
||||
|
||||
|
||||
+int Serializer::AllocateLargeObject(int size) {
|
||||
+ fullness_[LO_SPACE] += size;
|
||||
+ return seen_large_objects_index_++;
|
||||
+}
|
||||
+
|
||||
+
|
||||
int Serializer::Allocate(int space, int size) {
|
||||
- CHECK(space >= 0 && space < kNumberOfSpaces);
|
||||
+ CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
|
||||
int allocation_address = fullness_[space];
|
||||
fullness_[space] = allocation_address + size;
|
||||
return allocation_address;
|
||||
@@ -1840,11 +1894,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
|
||||
if (heap_object->IsCode()) {
|
||||
Code* code_object = Code::cast(heap_object);
|
||||
+ DCHECK(!code_object->is_optimized_code());
|
||||
if (code_object->kind() == Code::BUILTIN) {
|
||||
SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
||||
return;
|
||||
- }
|
||||
- if (code_object->IsCodeStubOrIC()) {
|
||||
+ } else if (code_object->IsCodeStubOrIC()) {
|
||||
SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
||||
return;
|
||||
}
|
||||
@@ -1991,7 +2045,7 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
|
||||
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
||||
Deserializer deserializer(&payload);
|
||||
STATIC_ASSERT(NEW_SPACE == 0);
|
||||
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
||||
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
|
||||
deserializer.set_reservation(i, scd.GetReservation(i));
|
||||
}
|
||||
|
||||
@@ -2041,7 +2095,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
||||
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
|
||||
SetHeaderValue(kPayloadLengthOffset, payload->length());
|
||||
STATIC_ASSERT(NEW_SPACE == 0);
|
||||
- for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
||||
+ for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
|
||||
SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
|
||||
}
|
||||
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 71b274b..7831536 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -148,11 +148,15 @@ class SerializerDeserializer: public ObjectVisitor {
|
||||
|
||||
static int nop() { return kNop; }
|
||||
|
||||
+ // No reservation for large object space necessary.
|
||||
+ static const int kNumberOfPreallocatedSpaces = LO_SPACE;
|
||||
+ static const int kNumberOfSpaces = INVALID_SPACE;
|
||||
+
|
||||
protected:
|
||||
// Where the pointed-to object can be found:
|
||||
enum Where {
|
||||
kNewObject = 0, // Object is next in snapshot.
|
||||
- // 1-6 One per space.
|
||||
+ // 1-7 One per space.
|
||||
kRootArray = 0x9, // Object is found in root array.
|
||||
kPartialSnapshotCache = 0xa, // Object is in the cache.
|
||||
kExternalReference = 0xb, // Pointer to an external reference.
|
||||
@@ -161,9 +165,9 @@ class SerializerDeserializer: public ObjectVisitor {
|
||||
kAttachedReference = 0xe, // Object is described in an attached list.
|
||||
kNop = 0xf, // Does nothing, used to pad.
|
||||
kBackref = 0x10, // Object is described relative to end.
|
||||
- // 0x11-0x16 One per space.
|
||||
+ // 0x11-0x17 One per space.
|
||||
kBackrefWithSkip = 0x18, // Object is described relative to end.
|
||||
- // 0x19-0x1e One per space.
|
||||
+ // 0x19-0x1f One per space.
|
||||
// 0x20-0x3f Used by misc. tags below.
|
||||
kPointedToMask = 0x3f
|
||||
};
|
||||
@@ -225,11 +229,11 @@ class SerializerDeserializer: public ObjectVisitor {
|
||||
return byte_code & 0x1f;
|
||||
}
|
||||
|
||||
- static const int kNumberOfSpaces = LO_SPACE;
|
||||
static const int kAnyOldSpace = -1;
|
||||
|
||||
// A bitmask for getting the space out of an instruction.
|
||||
static const int kSpaceMask = 7;
|
||||
+ STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
|
||||
};
|
||||
|
||||
|
||||
@@ -249,7 +253,7 @@ class Deserializer: public SerializerDeserializer {
|
||||
|
||||
void set_reservation(int space_number, int reservation) {
|
||||
DCHECK(space_number >= 0);
|
||||
- DCHECK(space_number <= LAST_SPACE);
|
||||
+ DCHECK(space_number < kNumberOfSpaces);
|
||||
reservations_[space_number] = reservation;
|
||||
}
|
||||
|
||||
@@ -282,24 +286,18 @@ class Deserializer: public SerializerDeserializer {
|
||||
void ReadChunk(
|
||||
Object** start, Object** end, int space, Address object_address);
|
||||
void ReadObject(int space_number, Object** write_back);
|
||||
+ Address Allocate(int space_index, int size);
|
||||
|
||||
// Special handling for serialized code like hooking up internalized strings.
|
||||
HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
|
||||
Object* ProcessBackRefInSerializedCode(Object* obj);
|
||||
|
||||
- // This routine both allocates a new object, and also keeps
|
||||
- // track of where objects have been allocated so that we can
|
||||
- // fix back references when deserializing.
|
||||
- Address Allocate(int space_index, int size) {
|
||||
- Address address = high_water_[space_index];
|
||||
- high_water_[space_index] = address + size;
|
||||
- return address;
|
||||
- }
|
||||
-
|
||||
// This returns the address of an object that has been described in the
|
||||
// snapshot as being offset bytes back in a particular space.
|
||||
HeapObject* GetAddressFromEnd(int space) {
|
||||
int offset = source_->GetInt();
|
||||
+ if (space == LO_SPACE) return deserialized_large_objects_[offset];
|
||||
+ DCHECK(space < kNumberOfPreallocatedSpaces);
|
||||
offset <<= kObjectAlignmentBits;
|
||||
return HeapObject::FromAddress(high_water_[space] - offset);
|
||||
}
|
||||
@@ -313,13 +311,15 @@ class Deserializer: public SerializerDeserializer {
|
||||
SnapshotByteSource* source_;
|
||||
// This is the address of the next object that will be allocated in each
|
||||
// space. It is used to calculate the addresses of back-references.
|
||||
- Address high_water_[LAST_SPACE + 1];
|
||||
+ Address high_water_[kNumberOfPreallocatedSpaces];
|
||||
|
||||
- int reservations_[LAST_SPACE + 1];
|
||||
+ int reservations_[kNumberOfSpaces];
|
||||
static const intptr_t kUninitializedReservation = -1;
|
||||
|
||||
ExternalReferenceDecoder* external_reference_decoder_;
|
||||
|
||||
+ List<HeapObject*> deserialized_large_objects_;
|
||||
+
|
||||
DISALLOW_COPY_AND_ASSIGN(Deserializer);
|
||||
};
|
||||
|
||||
@@ -466,6 +466,7 @@ class Serializer : public SerializerDeserializer {
|
||||
void InitializeAllocators();
|
||||
// This will return the space for an object.
|
||||
static int SpaceOfObject(HeapObject* object);
|
||||
+ int AllocateLargeObject(int size);
|
||||
int Allocate(int space, int size);
|
||||
int EncodeExternalReference(Address addr) {
|
||||
return external_reference_encoder_->Encode(addr);
|
||||
@@ -480,7 +481,7 @@ class Serializer : public SerializerDeserializer {
|
||||
Isolate* isolate_;
|
||||
// Keep track of the fullness of each space in order to generate
|
||||
// relative addresses for back references.
|
||||
- int fullness_[LAST_SPACE + 1];
|
||||
+ int fullness_[kNumberOfSpaces];
|
||||
SnapshotByteSink* sink_;
|
||||
ExternalReferenceEncoder* external_reference_encoder_;
|
||||
|
||||
@@ -497,6 +498,8 @@ class Serializer : public SerializerDeserializer {
|
||||
|
||||
private:
|
||||
CodeAddressMap* code_address_map_;
|
||||
+ // We map serialized large objects to indexes for back-referencing.
|
||||
+ int seen_large_objects_index_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
@@ -691,8 +694,8 @@ class SerializedCodeData {
|
||||
static const int kPayloadLengthOffset = 2;
|
||||
static const int kReservationsOffset = 3;
|
||||
|
||||
- static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
|
||||
- static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
|
||||
+ static const int kHeaderEntries =
|
||||
+ kReservationsOffset + SerializerDeserializer::kNumberOfSpaces;
|
||||
static const int kHeaderSize = kHeaderEntries * kIntSize;
|
||||
|
||||
// Following the header, we store, in sequential order
|
||||
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
|
||||
index a2d5213..4e90ce1 100644
|
||||
--- node/deps/v8/src/snapshot-common.cc
|
||||
+++ node/deps/v8/src/snapshot-common.cc
|
||||
@@ -21,8 +21,8 @@ void Snapshot::ReserveSpaceForLinkedInSnapshot(Deserializer* deserializer) {
|
||||
deserializer->set_reservation(CODE_SPACE, code_space_used_);
|
||||
deserializer->set_reservation(MAP_SPACE, map_space_used_);
|
||||
deserializer->set_reservation(CELL_SPACE, cell_space_used_);
|
||||
- deserializer->set_reservation(PROPERTY_CELL_SPACE,
|
||||
- property_cell_space_used_);
|
||||
+ deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_space_used_);
|
||||
+ deserializer->set_reservation(LO_SPACE, lo_space_used_);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
|
||||
deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
|
||||
deserializer.set_reservation(PROPERTY_CELL_SPACE,
|
||||
context_property_cell_space_used_);
|
||||
+ deserializer.set_reservation(LO_SPACE, context_lo_space_used_);
|
||||
deserializer.DeserializePartial(isolate, &root);
|
||||
CHECK(root->IsContext());
|
||||
return Handle<Context>(Context::cast(root));
|
||||
diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc
|
||||
index 65207bf..e8673e5 100644
|
||||
--- node/deps/v8/src/snapshot-empty.cc
|
||||
+++ node/deps/v8/src/snapshot-empty.cc
|
||||
@@ -27,6 +27,7 @@ const int Snapshot::code_space_used_ = 0;
|
||||
const int Snapshot::map_space_used_ = 0;
|
||||
const int Snapshot::cell_space_used_ = 0;
|
||||
const int Snapshot::property_cell_space_used_ = 0;
|
||||
+const int Snapshot::lo_space_used_ = 0;
|
||||
|
||||
const int Snapshot::context_new_space_used_ = 0;
|
||||
const int Snapshot::context_pointer_space_used_ = 0;
|
||||
@@ -35,5 +36,5 @@ const int Snapshot::context_code_space_used_ = 0;
|
||||
const int Snapshot::context_map_space_used_ = 0;
|
||||
const int Snapshot::context_cell_space_used_ = 0;
|
||||
const int Snapshot::context_property_cell_space_used_ = 0;
|
||||
-
|
||||
+const int Snapshot::context_lo_space_used_ = 0;
|
||||
} } // namespace v8::internal
|
||||
diff --git a/src/snapshot-external.cc b/src/snapshot-external.cc
|
||||
index ee1a8f4..9b8bc1b 100644
|
||||
--- node/deps/v8/src/snapshot-external.cc
|
||||
+++ node/deps/v8/src/snapshot-external.cc
|
||||
@@ -25,6 +25,7 @@ struct SnapshotImpl {
|
||||
int map_space_used;
|
||||
int cell_space_used;
|
||||
int property_cell_space_used;
|
||||
+ int lo_space_used;
|
||||
|
||||
const byte* context_data;
|
||||
int context_size;
|
||||
@@ -35,6 +36,7 @@ struct SnapshotImpl {
|
||||
int context_map_space_used;
|
||||
int context_cell_space_used;
|
||||
int context_property_cell_space_used;
|
||||
+ int context_lo_space_used;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,6 +68,7 @@ bool Snapshot::Initialize(Isolate* isolate) {
|
||||
deserializer.set_reservation(CELL_SPACE, snapshot_impl_->cell_space_used);
|
||||
deserializer.set_reservation(PROPERTY_CELL_SPACE,
|
||||
snapshot_impl_->property_cell_space_used);
|
||||
+ deserializer.set_reservation(LO_SPACE, snapshot_impl_->lo_space_used);
|
||||
bool success = V8::Initialize(&deserializer);
|
||||
if (FLAG_profile_deserialization) {
|
||||
double ms = timer.Elapsed().InMillisecondsF();
|
||||
@@ -97,6 +100,7 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
|
||||
deserializer.set_reservation(PROPERTY_CELL_SPACE,
|
||||
snapshot_impl_->
|
||||
context_property_cell_space_used);
|
||||
+ deserializer.set_reservation(LO_SPACE, snapshot_impl_->context_lo_space_used);
|
||||
Object* root;
|
||||
deserializer.DeserializePartial(isolate, &root);
|
||||
CHECK(root->IsContext());
|
||||
@@ -123,6 +127,7 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) {
|
||||
snapshot_impl_->map_space_used = source.GetInt();
|
||||
snapshot_impl_->cell_space_used = source.GetInt();
|
||||
snapshot_impl_->property_cell_space_used = source.GetInt();
|
||||
+ snapshot_impl_->lo_space_used = source.GetInt();
|
||||
|
||||
success &= source.GetBlob(&snapshot_impl_->context_data,
|
||||
&snapshot_impl_->context_size);
|
||||
diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc
|
||||
index 44f8706..29bad33 100644
|
||||
--- node/deps/v8/src/snapshot-source-sink.cc
|
||||
+++ node/deps/v8/src/snapshot-source-sink.cc
|
||||
@@ -39,15 +39,17 @@ void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
|
||||
|
||||
|
||||
void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
|
||||
- DCHECK(integer < 1 << 22);
|
||||
+ DCHECK(integer < 1 << 30);
|
||||
integer <<= 2;
|
||||
int bytes = 1;
|
||||
if (integer > 0xff) bytes = 2;
|
||||
if (integer > 0xffff) bytes = 3;
|
||||
- integer |= bytes;
|
||||
+ if (integer > 0xffffff) bytes = 4;
|
||||
+ integer |= (bytes - 1);
|
||||
Put(static_cast<int>(integer & 0xff), "IntPart1");
|
||||
if (bytes > 1) Put(static_cast<int>((integer >> 8) & 0xff), "IntPart2");
|
||||
if (bytes > 2) Put(static_cast<int>((integer >> 16) & 0xff), "IntPart3");
|
||||
+ if (bytes > 3) Put(static_cast<int>((integer >> 24) & 0xff), "IntPart4");
|
||||
}
|
||||
|
||||
void SnapshotByteSink::PutRaw(byte* data, int number_of_bytes,
|
||||
diff --git a/src/snapshot-source-sink.h b/src/snapshot-source-sink.h
|
||||
index 3c64bca..c1a31b5 100644
|
||||
--- node/deps/v8/src/snapshot-source-sink.h
|
||||
+++ node/deps/v8/src/snapshot-source-sink.h
|
||||
@@ -39,7 +39,7 @@ class SnapshotByteSource FINAL {
|
||||
// This way of variable-length encoding integers does not suffer from branch
|
||||
// mispredictions.
|
||||
uint32_t answer = GetUnalignedInt();
|
||||
- int bytes = answer & 3;
|
||||
+ int bytes = (answer & 3) + 1;
|
||||
Advance(bytes);
|
||||
uint32_t mask = 0xffffffffu;
|
||||
mask >>= 32 - (bytes << 3);
|
||||
diff --git a/src/snapshot.h b/src/snapshot.h
|
||||
index 3d752a7..590ecf1 100644
|
||||
--- node/deps/v8/src/snapshot.h
|
||||
+++ node/deps/v8/src/snapshot.h
|
||||
@@ -48,6 +48,7 @@ class Snapshot {
|
||||
static const int map_space_used_;
|
||||
static const int cell_space_used_;
|
||||
static const int property_cell_space_used_;
|
||||
+ static const int lo_space_used_;
|
||||
static const int context_new_space_used_;
|
||||
static const int context_pointer_space_used_;
|
||||
static const int context_data_space_used_;
|
||||
@@ -55,6 +56,7 @@ class Snapshot {
|
||||
static const int context_map_space_used_;
|
||||
static const int context_cell_space_used_;
|
||||
static const int context_property_cell_space_used_;
|
||||
+ static const int context_lo_space_used_;
|
||||
static const int size_;
|
||||
static const int raw_size_;
|
||||
static const int context_size_;
|
||||
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
|
||||
index c277011..ed9419d 100644
|
||||
--- node/deps/v8/test/cctest/test-serialize.cc
|
||||
+++ node/deps/v8/test/cctest/test-serialize.cc
|
||||
@@ -137,14 +137,10 @@ class FileByteSink : public SnapshotByteSink {
|
||||
virtual int Position() {
|
||||
return ftell(fp_);
|
||||
}
|
||||
- void WriteSpaceUsed(
|
||||
- int new_space_used,
|
||||
- int pointer_space_used,
|
||||
- int data_space_used,
|
||||
- int code_space_used,
|
||||
- int map_space_used,
|
||||
- int cell_space_used,
|
||||
- int property_cell_space_used);
|
||||
+ void WriteSpaceUsed(int new_space_used, int pointer_space_used,
|
||||
+ int data_space_used, int code_space_used,
|
||||
+ int map_space_used, int cell_space_used,
|
||||
+ int property_cell_space_used, int lo_space_used);
|
||||
|
||||
private:
|
||||
FILE* fp_;
|
||||
@@ -152,14 +148,11 @@ class FileByteSink : public SnapshotByteSink {
|
||||
};
|
||||
|
||||
|
||||
-void FileByteSink::WriteSpaceUsed(
|
||||
- int new_space_used,
|
||||
- int pointer_space_used,
|
||||
- int data_space_used,
|
||||
- int code_space_used,
|
||||
- int map_space_used,
|
||||
- int cell_space_used,
|
||||
- int property_cell_space_used) {
|
||||
+void FileByteSink::WriteSpaceUsed(int new_space_used, int pointer_space_used,
|
||||
+ int data_space_used, int code_space_used,
|
||||
+ int map_space_used, int cell_space_used,
|
||||
+ int property_cell_space_used,
|
||||
+ int lo_space_used) {
|
||||
int file_name_length = StrLength(file_name_) + 10;
|
||||
Vector<char> name = Vector<char>::New(file_name_length + 1);
|
||||
SNPrintF(name, "%s.size", file_name_);
|
||||
@@ -172,6 +165,7 @@ void FileByteSink::WriteSpaceUsed(
|
||||
fprintf(fp, "map %d\n", map_space_used);
|
||||
fprintf(fp, "cell %d\n", cell_space_used);
|
||||
fprintf(fp, "property cell %d\n", property_cell_space_used);
|
||||
+ fprintf(fp, "lo %d\n", lo_space_used);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
@@ -181,14 +175,14 @@ static bool WriteToFile(Isolate* isolate, const char* snapshot_file) {
|
||||
StartupSerializer ser(isolate, &file);
|
||||
ser.Serialize();
|
||||
|
||||
- file.WriteSpaceUsed(
|
||||
- ser.CurrentAllocationAddress(NEW_SPACE),
|
||||
- ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
|
||||
- ser.CurrentAllocationAddress(OLD_DATA_SPACE),
|
||||
- ser.CurrentAllocationAddress(CODE_SPACE),
|
||||
- ser.CurrentAllocationAddress(MAP_SPACE),
|
||||
- ser.CurrentAllocationAddress(CELL_SPACE),
|
||||
- ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
|
||||
+ file.WriteSpaceUsed(ser.CurrentAllocationAddress(NEW_SPACE),
|
||||
+ ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
|
||||
+ ser.CurrentAllocationAddress(OLD_DATA_SPACE),
|
||||
+ ser.CurrentAllocationAddress(CODE_SPACE),
|
||||
+ ser.CurrentAllocationAddress(MAP_SPACE),
|
||||
+ ser.CurrentAllocationAddress(CELL_SPACE),
|
||||
+ ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE),
|
||||
+ ser.CurrentAllocationAddress(LO_SPACE));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -246,7 +240,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
|
||||
FILE* fp = v8::base::OS::FOpen(name.start(), "r");
|
||||
name.Dispose();
|
||||
int new_size, pointer_size, data_size, code_size, map_size, cell_size,
|
||||
- property_cell_size;
|
||||
+ property_cell_size, lo_size;
|
||||
#ifdef _MSC_VER
|
||||
// Avoid warning about unsafe fscanf from MSVC.
|
||||
// Please note that this is only fine if %c and %s are not being used.
|
||||
@@ -259,6 +253,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
|
||||
CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
|
||||
CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
|
||||
CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
|
||||
+ CHECK_EQ(1, fscanf(fp, "lo %d\n", &lo_size));
|
||||
#ifdef _MSC_VER
|
||||
#undef fscanf
|
||||
#endif
|
||||
@@ -270,6 +265,7 @@ static void ReserveSpaceForSnapshot(Deserializer* deserializer,
|
||||
deserializer->set_reservation(MAP_SPACE, map_size);
|
||||
deserializer->set_reservation(CELL_SPACE, cell_size);
|
||||
deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
|
||||
+ deserializer->set_reservation(LO_SPACE, lo_size);
|
||||
}
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
commit 667f15a1047eeadf4cbadbb50dafe6541745cdc3
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Mon Sep 29 07:14:05 2014 +0000
|
||||
|
||||
Fix serializing ICs.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/587213002
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 894a1be..a2dde9b 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1894,15 +1894,26 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
|
||||
if (heap_object->IsCode()) {
|
||||
Code* code_object = Code::cast(heap_object);
|
||||
- DCHECK(!code_object->is_optimized_code());
|
||||
- if (code_object->kind() == Code::BUILTIN) {
|
||||
- SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
||||
- return;
|
||||
- } else if (code_object->IsCodeStubOrIC()) {
|
||||
- SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
||||
- return;
|
||||
+ switch (code_object->kind()) {
|
||||
+ case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet.
|
||||
+ case Code::HANDLER: // No handlers patched in yet.
|
||||
+ case Code::REGEXP: // No regexp literals initialized yet.
|
||||
+ case Code::NUMBER_OF_KINDS: // Pseudo enum value.
|
||||
+ CHECK(false);
|
||||
+ case Code::BUILTIN:
|
||||
+ SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
||||
+ return;
|
||||
+ case Code::STUB:
|
||||
+ SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
||||
+ return;
|
||||
+#define IC_KIND_CASE(KIND) case Code::KIND:
|
||||
+ IC_KIND_LIST(IC_KIND_CASE)
|
||||
+#undef IC_KIND_CASE
|
||||
+ // TODO(yangguo): add special handling to canonicalize ICs.
|
||||
+ case Code::FUNCTION:
|
||||
+ SerializeHeapObject(code_object, how_to_code, where_to_point, skip);
|
||||
+ return;
|
||||
}
|
||||
- code_object->ClearInlineCaches();
|
||||
}
|
||||
|
||||
if (heap_object == source_) {
|
||||
@@ -1967,20 +1978,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
}
|
||||
|
||||
|
||||
-void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code,
|
||||
+void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip) {
|
||||
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
|
||||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
|
||||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
|
||||
- uint32_t stub_key = code->stub_key();
|
||||
-
|
||||
- if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) {
|
||||
- if (FLAG_trace_code_serializer) {
|
||||
- PrintF("Encoding uncacheable code stub as heap object\n");
|
||||
- }
|
||||
- SerializeHeapObject(code, how_to_code, where_to_point, skip);
|
||||
- return;
|
||||
- }
|
||||
+ uint32_t stub_key = stub->stub_key();
|
||||
+ DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
|
||||
|
||||
if (skip != 0) {
|
||||
sink_->Put(kSkip, "SkipFromSerializeCodeStub");
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 7831536..b6ad82c 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -607,7 +607,7 @@ class CodeSerializer : public Serializer {
|
||||
private:
|
||||
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip);
|
||||
- void SerializeCodeStub(Code* code, HowToCode how_to_code,
|
||||
+ void SerializeCodeStub(Code* stub, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip);
|
||||
void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
|
||||
int skip);
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
commit ad24cdae728fc34b23e74a22543702de3ae477d1
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Mon Sep 29 07:53:22 2014 +0000
|
||||
|
||||
Do not serialize non-lazy compiled function literals.
|
||||
|
||||
... and some small refactorings.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/594513002
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24266 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index a2dde9b..9d59b6f 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1846,7 +1846,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
|
||||
SnapshotByteSink* sink = FLAG_trace_code_serializer
|
||||
? static_cast<SnapshotByteSink*>(&debug_sink)
|
||||
: static_cast<SnapshotByteSink*>(&list_sink);
|
||||
- CodeSerializer cs(isolate, sink, *source);
|
||||
+ CodeSerializer cs(isolate, sink, *source, info->code());
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object** location = Handle<Object>::cast(info).location();
|
||||
cs.VisitPointer(location);
|
||||
@@ -1867,31 +1867,25 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
|
||||
|
||||
void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
WhereToPoint where_to_point, int skip) {
|
||||
- CHECK(o->IsHeapObject());
|
||||
HeapObject* heap_object = HeapObject::cast(o);
|
||||
|
||||
- // The code-caches link to context-specific code objects, which
|
||||
- // the startup and context serializes cannot currently handle.
|
||||
- DCHECK(!heap_object->IsMap() ||
|
||||
- Map::cast(heap_object)->code_cache() ==
|
||||
- heap_object->GetHeap()->empty_fixed_array());
|
||||
-
|
||||
int root_index;
|
||||
if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
|
||||
PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
|
||||
return;
|
||||
}
|
||||
|
||||
- // TODO(yangguo) wire up global object.
|
||||
- // TODO(yangguo) We cannot deal with different hash seeds yet.
|
||||
- DCHECK(!heap_object->IsHashTable());
|
||||
-
|
||||
if (address_mapper_.IsMapped(heap_object)) {
|
||||
SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
||||
skip);
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (skip != 0) {
|
||||
+ sink_->Put(kSkip, "SkipFromSerializeObject");
|
||||
+ sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
|
||||
+ }
|
||||
+
|
||||
if (heap_object->IsCode()) {
|
||||
Code* code_object = Code::cast(heap_object);
|
||||
switch (code_object->kind()) {
|
||||
@@ -1901,34 +1895,42 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
case Code::NUMBER_OF_KINDS: // Pseudo enum value.
|
||||
CHECK(false);
|
||||
case Code::BUILTIN:
|
||||
- SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
||||
+ SerializeBuiltin(code_object, how_to_code, where_to_point);
|
||||
return;
|
||||
case Code::STUB:
|
||||
- SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
||||
+ SerializeCodeStub(code_object, how_to_code, where_to_point);
|
||||
return;
|
||||
#define IC_KIND_CASE(KIND) case Code::KIND:
|
||||
IC_KIND_LIST(IC_KIND_CASE)
|
||||
#undef IC_KIND_CASE
|
||||
+ SerializeHeapObject(code_object, how_to_code, where_to_point);
|
||||
+ return;
|
||||
// TODO(yangguo): add special handling to canonicalize ICs.
|
||||
case Code::FUNCTION:
|
||||
- SerializeHeapObject(code_object, how_to_code, where_to_point, skip);
|
||||
+ SerializeHeapObject(code_object, how_to_code, where_to_point);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (heap_object == source_) {
|
||||
- SerializeSourceObject(how_to_code, where_to_point, skip);
|
||||
+ SerializeSourceObject(how_to_code, where_to_point);
|
||||
return;
|
||||
}
|
||||
|
||||
- SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
|
||||
+ // Past this point we should not see any (context-specific) maps anymore.
|
||||
+ CHECK(!heap_object->IsMap());
|
||||
+ // There should be no references to the global object embedded.
|
||||
+ CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject());
|
||||
+ // There should be no hash table embedded. They would require rehashing.
|
||||
+ CHECK(!heap_object->IsHashTable());
|
||||
+
|
||||
+ SerializeHeapObject(heap_object, how_to_code, where_to_point);
|
||||
}
|
||||
|
||||
|
||||
void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
||||
HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point,
|
||||
- int skip) {
|
||||
+ WhereToPoint where_to_point) {
|
||||
if (heap_object->IsScript()) {
|
||||
// The wrapper cache uses a Foreign object to point to a global handle.
|
||||
// However, the object visitor expects foreign objects to point to external
|
||||
@@ -1936,11 +1946,6 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
||||
Script::cast(heap_object)->ClearWrapperCache();
|
||||
}
|
||||
|
||||
- if (skip != 0) {
|
||||
- sink_->Put(kSkip, "SkipFromSerializeObject");
|
||||
- sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
|
||||
- }
|
||||
-
|
||||
if (FLAG_trace_code_serializer) {
|
||||
PrintF("Encoding heap object: ");
|
||||
heap_object->ShortPrint();
|
||||
@@ -1955,12 +1960,7 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
||||
|
||||
|
||||
void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip) {
|
||||
- if (skip != 0) {
|
||||
- sink_->Put(kSkip, "SkipFromSerializeBuiltin");
|
||||
- sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin");
|
||||
- }
|
||||
-
|
||||
+ WhereToPoint where_to_point) {
|
||||
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
|
||||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
|
||||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
|
||||
@@ -1979,18 +1979,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
|
||||
|
||||
void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip) {
|
||||
+ WhereToPoint where_to_point) {
|
||||
DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
|
||||
(how_to_code == kPlain && where_to_point == kInnerPointer) ||
|
||||
(how_to_code == kFromCode && where_to_point == kInnerPointer));
|
||||
uint32_t stub_key = stub->stub_key();
|
||||
DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
|
||||
|
||||
- if (skip != 0) {
|
||||
- sink_->Put(kSkip, "SkipFromSerializeCodeStub");
|
||||
- sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
|
||||
- }
|
||||
-
|
||||
int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
|
||||
|
||||
if (FLAG_trace_code_serializer) {
|
||||
@@ -2017,16 +2012,8 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
|
||||
|
||||
|
||||
void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point,
|
||||
- int skip) {
|
||||
- if (skip != 0) {
|
||||
- sink_->Put(kSkip, "SkipFromSerializeSourceObject");
|
||||
- sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
|
||||
- }
|
||||
-
|
||||
- if (FLAG_trace_code_serializer) {
|
||||
- PrintF("Encoding source object\n");
|
||||
- }
|
||||
+ WhereToPoint where_to_point) {
|
||||
+ if (FLAG_trace_code_serializer) PrintF("Encoding source object\n");
|
||||
|
||||
DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
|
||||
sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index b6ad82c..616f8f1 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -577,19 +577,10 @@ class StartupSerializer : public Serializer {
|
||||
|
||||
class CodeSerializer : public Serializer {
|
||||
public:
|
||||
- CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
|
||||
- : Serializer(isolate, sink), source_(source) {
|
||||
- set_root_index_wave_front(Heap::kStrongRootListLength);
|
||||
- InitializeCodeAddressMap();
|
||||
- }
|
||||
-
|
||||
static ScriptData* Serialize(Isolate* isolate,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<String> source);
|
||||
|
||||
- virtual void SerializeObject(Object* o, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip);
|
||||
-
|
||||
static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
|
||||
ScriptData* data,
|
||||
Handle<String> source);
|
||||
@@ -605,18 +596,29 @@ class CodeSerializer : public Serializer {
|
||||
List<uint32_t>* stub_keys() { return &stub_keys_; }
|
||||
|
||||
private:
|
||||
+ CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
|
||||
+ Code* main_code)
|
||||
+ : Serializer(isolate, sink), source_(source), main_code_(main_code) {
|
||||
+ set_root_index_wave_front(Heap::kStrongRootListLength);
|
||||
+ InitializeCodeAddressMap();
|
||||
+ }
|
||||
+
|
||||
+ virtual void SerializeObject(Object* o, HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point, int skip);
|
||||
+
|
||||
void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip);
|
||||
+ WhereToPoint where_to_point);
|
||||
void SerializeCodeStub(Code* stub, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip);
|
||||
- void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
|
||||
- int skip);
|
||||
+ WhereToPoint where_to_point);
|
||||
+ void SerializeSourceObject(HowToCode how_to_code,
|
||||
+ WhereToPoint where_to_point);
|
||||
void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
|
||||
- WhereToPoint where_to_point, int skip);
|
||||
+ WhereToPoint where_to_point);
|
||||
int AddCodeStubKey(uint32_t stub_key);
|
||||
|
||||
DisallowHeapAllocation no_gc_;
|
||||
String* source_;
|
||||
+ Code* main_code_;
|
||||
List<uint32_t> stub_keys_;
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
|
||||
};
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
commit 6ca8f782aac4df7530d9fd460ec0fabd46628e1d
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Fri Oct 10 10:51:34 2014 +0000
|
||||
|
||||
Reset code age when serializing code objects.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/642283002
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24523 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/objects.cc b/src/objects.cc
|
||||
index 9f25145..3eedfe9 100644
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -10463,6 +10463,12 @@ static Code::Age EffectiveAge(Code::Age age) {
|
||||
}
|
||||
|
||||
|
||||
+void Code::MakeYoung() {
|
||||
+ byte* sequence = FindCodeAgeSequence();
|
||||
+ if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, GetIsolate());
|
||||
+}
|
||||
+
|
||||
+
|
||||
void Code::MakeOlder(MarkingParity current_parity) {
|
||||
byte* sequence = FindCodeAgeSequence();
|
||||
if (sequence != NULL) {
|
||||
diff --git a/src/objects.h b/src/objects.h
|
||||
index bcbea12..1faae86 100644
|
||||
--- node/deps/v8/src/objects.h
|
||||
+++ node/deps/v8/src/objects.h
|
||||
@@ -5310,6 +5310,7 @@ class Code: public HeapObject {
|
||||
// compilation stub.
|
||||
static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate);
|
||||
static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate);
|
||||
+ void MakeYoung();
|
||||
void MakeOlder(MarkingParity);
|
||||
static bool IsYoungSequence(Isolate* isolate, byte* sequence);
|
||||
bool IsOld();
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 0cc629d..c287219 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1991,6 +1991,7 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
||||
return;
|
||||
// TODO(yangguo): add special handling to canonicalize ICs.
|
||||
case Code::FUNCTION:
|
||||
+ code_object->MakeYoung();
|
||||
SerializeHeapObject(code_object, how_to_code, where_to_point);
|
||||
return;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
commit 33dc53f9cc709862de641d32c9a412cf7cfce953
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Mon Oct 13 07:50:21 2014 +0000
|
||||
|
||||
Always include full reloc info to stubs for serialization.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/641643006
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24543 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
||||
index 80fff3f..63488dc 100644
|
||||
--- node/deps/v8/src/code-stubs-hydrogen.cc
|
||||
+++ node/deps/v8/src/code-stubs-hydrogen.cc
|
||||
@@ -233,6 +233,8 @@ Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(
|
||||
|
||||
// Generate the code for the stub.
|
||||
masm.set_generating_stub(true);
|
||||
+ // TODO(yangguo): remove this once we can serialize IC stubs.
|
||||
+ masm.enable_serializer();
|
||||
NoCurrentFrameScope scope(&masm);
|
||||
GenerateLightweightMiss(&masm, miss);
|
||||
}
|
||||
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
||||
index 357324b..9832650 100644
|
||||
--- node/deps/v8/src/code-stubs.cc
|
||||
+++ node/deps/v8/src/code-stubs.cc
|
||||
@@ -111,6 +111,8 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
|
||||
|
||||
// Generate the code for the stub.
|
||||
masm.set_generating_stub(true);
|
||||
+ // TODO(yangguo): remove this once we can serialize IC stubs.
|
||||
+ masm.enable_serializer();
|
||||
NoCurrentFrameScope scope(&masm);
|
||||
Generate(&masm);
|
||||
}
|
||||
+1062
File diff suppressed because it is too large
Load Diff
+25
@@ -0,0 +1,25 @@
|
||||
commit d7acb9148b6407526c257eceaec16c358655a3d5
|
||||
Author: jkummerow@chromium.org <jkummerow@chromium.org>
|
||||
Date: Wed Oct 15 14:27:26 2014 +0000
|
||||
|
||||
Fix compilation after r24639
|
||||
|
||||
TBR=yangguo@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/661473002
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24642 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 4c9675e..b980940 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1918,7 +1918,7 @@ uint32_t Serializer::Allocate(int space, int size) {
|
||||
DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
|
||||
uint32_t new_chunk_size = pending_chunk_[space] + size;
|
||||
uint32_t allocation;
|
||||
- if (new_chunk_size > Page::kMaxRegularHeapObjectSize) {
|
||||
+ if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
|
||||
// The new chunk size would not fit onto a single page. Complete the
|
||||
// current chunk and start a new one.
|
||||
completed_chunks_[space].Add(pending_chunk_[space]);
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
commit 2577d6c261da26d6fbc97669a3ef8f4b61027c7e
|
||||
Author: sigurds@chromium.org <sigurds@chromium.org>
|
||||
Date: Wed Oct 15 14:42:32 2014 +0000
|
||||
|
||||
Fix compilation after r24639
|
||||
|
||||
TBR=yangguo@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/653353003
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24643 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 6e1f651..482bc34 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -263,7 +263,8 @@ class Deserializer: public SerializerDeserializer {
|
||||
void AddReservation(int space, uint32_t chunk) {
|
||||
DCHECK(space >= 0);
|
||||
DCHECK(space < kNumberOfSpaces);
|
||||
- DCHECK(space == LO_SPACE || chunk < Page::kMaxRegularHeapObjectSize);
|
||||
+ DCHECK(space == LO_SPACE ||
|
||||
+ chunk < static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
commit 8949d5f58002c5d058064e9047a6247119e725bf
|
||||
Author: jkummerow@chromium.org <jkummerow@chromium.org>
|
||||
Date: Wed Oct 15 15:04:09 2014 +0000
|
||||
|
||||
Fix compilation some more after r24639
|
||||
|
||||
Third time's a charm...
|
||||
|
||||
TBR=yangguo@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/655223003
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24644 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index b980940..4933a19 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -2213,7 +2213,9 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
||||
for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
|
||||
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
|
||||
for (int j = 0; j < chunks.length(); j++) {
|
||||
- DCHECK(i == LO_SPACE || chunks[j] < Page::kMaxRegularHeapObjectSize);
|
||||
+ DCHECK(i == LO_SPACE ||
|
||||
+ chunks[j] <
|
||||
+ static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
|
||||
IsLastChunkBits::encode(j == chunks.length() - 1);
|
||||
reservations.Add(chunk);
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
commit 7753ace1354ac231374da0446a5057b6b40780db
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Thu Oct 23 08:25:42 2014 +0000
|
||||
|
||||
Small fixes for the code serializer.
|
||||
- assertions regarding max heap object size.
|
||||
- ensure string table capacity upfront.
|
||||
|
||||
R=mvstanton@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/671843003
|
||||
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24824 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/objects.cc b/src/objects.cc
|
||||
index 2685a5c..371931c 100644
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -14769,6 +14769,16 @@ MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
|
||||
}
|
||||
|
||||
|
||||
+void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
|
||||
+ int expected) {
|
||||
+ Handle<StringTable> table = isolate->factory()->string_table();
|
||||
+ // We need a key instance for the virtual hash function.
|
||||
+ InternalizedStringKey dummy_key(Handle<String>::null());
|
||||
+ table = StringTable::EnsureCapacity(table, expected, &dummy_key);
|
||||
+ isolate->factory()->set_string_table(table);
|
||||
+}
|
||||
+
|
||||
+
|
||||
Handle<String> StringTable::LookupString(Isolate* isolate,
|
||||
Handle<String> string) {
|
||||
InternalizedStringKey key(string);
|
||||
diff --git a/src/objects.h b/src/objects.h
|
||||
index 7e509e7..b2b64c2 100644
|
||||
--- node/deps/v8/src/objects.h
|
||||
+++ node/deps/v8/src/objects.h
|
||||
@@ -3446,6 +3446,8 @@ class StringTable: public HashTable<StringTable,
|
||||
uint16_t c1,
|
||||
uint16_t c2);
|
||||
|
||||
+ static void EnsureCapacityForDeserialization(Isolate* isolate, int expected);
|
||||
+
|
||||
DECLARE_CAST(StringTable)
|
||||
|
||||
private:
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 5e6de03..95336fb 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1910,7 +1913,7 @@ uint32_t Serializer::AllocateLargeObject(int size) {
|
||||
|
||||
uint32_t Serializer::Allocate(int space, int size) {
|
||||
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
|
||||
- DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
|
||||
+ DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
|
||||
uint32_t new_chunk_size = pending_chunk_[space] + size;
|
||||
uint32_t allocation;
|
||||
if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
|
||||
@@ -2081,6 +2084,8 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
||||
PrintF("\n");
|
||||
}
|
||||
|
||||
+ if (heap_object->IsInternalizedString()) num_internalized_strings_++;
|
||||
+
|
||||
// Object has not yet been serialized. Serialize it here.
|
||||
ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
|
||||
where_to_point);
|
||||
@@ -2201,6 +2206,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
|
||||
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
||||
Deserializer deserializer(&payload);
|
||||
|
||||
+ // Eagerly expand string table to avoid allocations during deserialization.
|
||||
+ StringTable::EnsureCapacityForDeserialization(isolate,
|
||||
+ scd.NumInternalizedStrings());
|
||||
+
|
||||
+ // Set reservations.
|
||||
STATIC_ASSERT(NEW_SPACE == 0);
|
||||
int current_space = NEW_SPACE;
|
||||
Vector<const SerializedCodeData::Reservation> res = scd.Reservations();
|
||||
@@ -2254,7 +2264,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
||||
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
|
||||
for (int j = 0; j < chunks.length(); j++) {
|
||||
DCHECK(i == LO_SPACE ||
|
||||
- chunks[j] <
|
||||
+ chunks[j] <=
|
||||
static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
|
||||
IsLastChunkBits::encode(j == chunks.length() - 1);
|
||||
@@ -2277,6 +2287,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
||||
|
||||
// Set header values.
|
||||
SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
|
||||
+ SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings());
|
||||
SetHeaderValue(kReservationsOffset, reservations.length());
|
||||
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
|
||||
SetHeaderValue(kPayloadLengthOffset, payload->length());
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 47a244f..df6723c 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -264,7 +264,7 @@ class Deserializer: public SerializerDeserializer {
|
||||
DCHECK(space >= 0);
|
||||
DCHECK(space < kNumberOfSpaces);
|
||||
DCHECK(space == LO_SPACE ||
|
||||
- chunk < static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
+ chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
|
||||
}
|
||||
|
||||
@@ -619,17 +619,21 @@ class CodeSerializer : public Serializer {
|
||||
static const int kSourceObjectIndex = 0;
|
||||
static const int kCodeStubsBaseIndex = 1;
|
||||
|
||||
- String* source() {
|
||||
+ String* source() const {
|
||||
DCHECK(!AllowHeapAllocation::IsAllowed());
|
||||
return source_;
|
||||
}
|
||||
|
||||
List<uint32_t>* stub_keys() { return &stub_keys_; }
|
||||
+ int num_internalized_strings() const { return num_internalized_strings_; }
|
||||
|
||||
private:
|
||||
CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
|
||||
Code* main_code)
|
||||
- : Serializer(isolate, sink), source_(source), main_code_(main_code) {
|
||||
+ : Serializer(isolate, sink),
|
||||
+ source_(source),
|
||||
+ main_code_(main_code),
|
||||
+ num_internalized_strings_(0) {
|
||||
set_root_index_wave_front(Heap::kStrongRootListLength);
|
||||
InitializeCodeAddressMap();
|
||||
}
|
||||
@@ -652,6 +656,7 @@ class CodeSerializer : public Serializer {
|
||||
DisallowHeapAllocation no_gc_;
|
||||
String* source_;
|
||||
Code* main_code_;
|
||||
+ int num_internalized_strings_;
|
||||
List<uint32_t> stub_keys_;
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
|
||||
};
|
||||
@@ -694,6 +699,10 @@ class SerializedCodeData {
|
||||
DISALLOW_COPY_AND_ASSIGN(Reservation);
|
||||
};
|
||||
|
||||
+ int NumInternalizedStrings() const {
|
||||
+ return GetHeaderValue(kNumInternalizedStringsOffset);
|
||||
+ }
|
||||
+
|
||||
Vector<const Reservation> Reservations() const {
|
||||
return Vector<const Reservation>(reinterpret_cast<const Reservation*>(
|
||||
script_data_->data() + kHeaderSize),
|
||||
@@ -737,13 +746,15 @@ class SerializedCodeData {
|
||||
|
||||
// The data header consists of int-sized entries:
|
||||
// [0] version hash
|
||||
- // [1] number of code stub keys
|
||||
- // [2] payload length
|
||||
- // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
|
||||
+ // [1] number of internalized strings
|
||||
+ // [2] number of code stub keys
|
||||
+ // [3] payload length
|
||||
+ // [4..10] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
|
||||
static const int kCheckSumOffset = 0;
|
||||
- static const int kReservationsOffset = 1;
|
||||
- static const int kNumCodeStubKeysOffset = 2;
|
||||
- static const int kPayloadLengthOffset = 3;
|
||||
+ static const int kNumInternalizedStringsOffset = 1;
|
||||
+ static const int kReservationsOffset = 2;
|
||||
+ static const int kNumCodeStubKeysOffset = 3;
|
||||
+ static const int kPayloadLengthOffset = 4;
|
||||
static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize;
|
||||
|
||||
class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
commit 3a3d5e741a4329641fa45f7293220e8dfd7a8f15
|
||||
Author: yangguo@chromium.org <yangguo@chromium.org>
|
||||
Date: Fri Oct 31 14:43:21 2014 +0000
|
||||
|
||||
Break allocations in the code serializer into correct chunk sizes.
|
||||
|
||||
This change has been inspired by Slava Chigrin <vchigrin@yandex-team.ru> (https://codereview.chromium.org/689663002/)
|
||||
|
||||
R=mvstanton@chromium.org, vchigrin@yandex-team.ru
|
||||
|
||||
Review URL: https://codereview.chromium.org/686103004
|
||||
|
||||
Cr-Commit-Position: refs/heads/master@{#25039}
|
||||
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25039 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
|
||||
|
||||
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
|
||||
index 94c8937..93e00d2 100644
|
||||
--- node/deps/v8/src/heap/heap.cc
|
||||
+++ node/deps/v8/src/heap/heap.cc
|
||||
@@ -939,6 +939,8 @@ bool Heap::ReserveSpace(Reservation* reservations) {
|
||||
for (auto& chunk : *reservation) {
|
||||
AllocationResult allocation;
|
||||
int size = chunk.size;
|
||||
+ DCHECK_LE(size, MemoryAllocator::PageAreaSize(
|
||||
+ static_cast<AllocationSpace>(space)));
|
||||
if (space == NEW_SPACE) {
|
||||
allocation = new_space()->AllocateRaw(size);
|
||||
} else {
|
||||
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
|
||||
index 85281aa..430f31d 100644
|
||||
--- node/deps/v8/src/heap/spaces.cc
|
||||
+++ node/deps/v8/src/heap/spaces.cc
|
||||
@@ -892,19 +892,15 @@ void MemoryChunk::IncrementLiveBytesFromMutator(Address address, int by) {
|
||||
// -----------------------------------------------------------------------------
|
||||
// PagedSpace implementation
|
||||
|
||||
-PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id,
|
||||
+PagedSpace::PagedSpace(Heap* heap, intptr_t max_capacity, AllocationSpace space,
|
||||
Executability executable)
|
||||
- : Space(heap, id, executable),
|
||||
+ : Space(heap, space, executable),
|
||||
free_list_(this),
|
||||
swept_precisely_(true),
|
||||
unswept_free_bytes_(0),
|
||||
end_of_unswept_pages_(NULL),
|
||||
emergency_memory_(NULL) {
|
||||
- if (id == CODE_SPACE) {
|
||||
- area_size_ = heap->isolate()->memory_allocator()->CodePageAreaSize();
|
||||
- } else {
|
||||
- area_size_ = Page::kPageSize - Page::kObjectStartOffset;
|
||||
- }
|
||||
+ area_size_ = MemoryAllocator::PageAreaSize(space);
|
||||
max_capacity_ =
|
||||
(RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) * AreaSize();
|
||||
accounting_stats_.Clear();
|
||||
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
|
||||
index 5be9c3a..1944464 100644
|
||||
--- node/deps/v8/src/heap/spaces.h
|
||||
+++ node/deps/v8/src/heap/spaces.h
|
||||
@@ -1104,6 +1104,12 @@ class MemoryAllocator {
|
||||
return CodePageAreaEndOffset() - CodePageAreaStartOffset();
|
||||
}
|
||||
|
||||
+ static int PageAreaSize(AllocationSpace space) {
|
||||
+ DCHECK_NE(LO_SPACE, space);
|
||||
+ return (space == CODE_SPACE) ? CodePageAreaSize()
|
||||
+ : Page::kMaxRegularHeapObjectSize;
|
||||
+ }
|
||||
+
|
||||
MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm,
|
||||
Address start, size_t commit_size,
|
||||
size_t reserved_size);
|
||||
diff --git a/src/serialize.cc b/src/serialize.cc
|
||||
index 86045d3..df62adb 100644
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -1258,10 +1258,15 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
|
||||
external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
|
||||
root_index_map_(isolate),
|
||||
code_address_map_(NULL),
|
||||
+ large_objects_total_size_(0),
|
||||
seen_large_objects_index_(0) {
|
||||
// The serializer is meant to be used only to generate initial heap images
|
||||
// from a context in which there is only one isolate.
|
||||
- for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0;
|
||||
+ for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
|
||||
+ pending_chunk_[i] = 0;
|
||||
+ max_chunk_size_[i] = static_cast<uint32_t>(
|
||||
+ MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i)));
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -1336,8 +1341,7 @@ void Serializer::VisitPointers(Object** start, Object** end) {
|
||||
|
||||
|
||||
void Serializer::FinalizeAllocation() {
|
||||
- DCHECK_EQ(0, completed_chunks_[LO_SPACE].length()); // Not yet finalized.
|
||||
- for (int i = 0; i < kNumberOfSpaces; i++) {
|
||||
+ for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
|
||||
// Complete the last pending chunk and if there are no completed chunks,
|
||||
// make sure there is at least one empty chunk.
|
||||
if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) {
|
||||
@@ -1906,17 +1910,17 @@ AllocationSpace Serializer::SpaceOfObject(HeapObject* object) {
|
||||
uint32_t Serializer::AllocateLargeObject(int size) {
|
||||
// Large objects are allocated one-by-one when deserializing. We do not
|
||||
// have to keep track of multiple chunks.
|
||||
- pending_chunk_[LO_SPACE] += size;
|
||||
+ large_objects_total_size_ += size;
|
||||
return seen_large_objects_index_++;
|
||||
}
|
||||
|
||||
|
||||
uint32_t Serializer::Allocate(int space, int size) {
|
||||
CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
|
||||
- DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
|
||||
+ DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
|
||||
uint32_t new_chunk_size = pending_chunk_[space] + size;
|
||||
uint32_t allocation;
|
||||
- if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
|
||||
+ if (new_chunk_size > max_chunk_size(space)) {
|
||||
// The new chunk size would not fit onto a single page. Complete the
|
||||
// current chunk and start a new one.
|
||||
completed_chunks_[space].Add(pending_chunk_[space]);
|
||||
@@ -1929,15 +1933,6 @@ BackReference Serializer::Allocate(AllocationSpace space, int size) {
|
||||
}
|
||||
|
||||
|
||||
-int Serializer::SpaceAreaSize(int space) {
|
||||
- if (space == CODE_SPACE) {
|
||||
- return isolate_->memory_allocator()->CodePageAreaSize();
|
||||
- } else {
|
||||
- return Page::kPageSize - Page::kObjectStartOffset;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
void Serializer::Pad() {
|
||||
// The non-branching GetInt will read up to 3 bytes too far, so we need
|
||||
// to pad the snapshot to make sure we don't read over the end.
|
||||
@@ -2273,9 +2268,6 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
||||
for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) {
|
||||
Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
|
||||
for (int j = 0; j < chunks.length(); j++) {
|
||||
- DCHECK(i == LO_SPACE ||
|
||||
- chunks[j] <=
|
||||
- static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
|
||||
IsLastChunkBits::encode(j == chunks.length() - 1);
|
||||
reservations.Add(chunk);
|
||||
diff --git a/src/serialize.h b/src/serialize.h
|
||||
index 2aa55ea..9c56118 100644
|
||||
--- node/deps/v8/src/serialize.h
|
||||
+++ node/deps/v8/src/serialize.h
|
||||
@@ -404,8 +404,6 @@ class Deserializer: public SerializerDeserializer {
|
||||
void AddReservation(int space, uint32_t chunk) {
|
||||
DCHECK(space >= 0);
|
||||
DCHECK(space < kNumberOfSpaces);
|
||||
- DCHECK(space == LO_SPACE ||
|
||||
- chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
|
||||
Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
|
||||
}
|
||||
|
||||
@@ -498,9 +496,12 @@ class Serializer : public SerializerDeserializer {
|
||||
void FinalizeAllocation();
|
||||
|
||||
Vector<const uint32_t> FinalAllocationChunks(int space) const {
|
||||
- DCHECK_EQ(1, completed_chunks_[LO_SPACE].length()); // Already finalized.
|
||||
- DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks.
|
||||
- return completed_chunks_[space].ToConstVector();
|
||||
+ if (space == LO_SPACE) {
|
||||
+ return Vector<const uint32_t>(&large_objects_total_size_, 1);
|
||||
+ } else {
|
||||
+ DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks.
|
||||
+ return completed_chunks_[space].ToConstVector();
|
||||
+ }
|
||||
}
|
||||
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
@@ -496,20 +496,25 @@
|
||||
return external_reference_encoder_->Encode(addr);
|
||||
}
|
||||
|
||||
- int SpaceAreaSize(int space);
|
||||
-
|
||||
// Some roots should not be serialized, because their actual value depends on
|
||||
// absolute addresses and they are reset after deserialization, anyway.
|
||||
bool ShouldBeSkipped(Object** current);
|
||||
|
||||
+ uint32_t max_chunk_size(int space) const {
|
||||
+ DCHECK_LE(0, space);
|
||||
+ DCHECK_LT(space, kNumberOfSpaces);
|
||||
+ return max_chunk_size_[space];
|
||||
+ }
|
||||
+
|
||||
Isolate* isolate_;
|
||||
|
||||
// Objects from the same space are put into chunks for bulk-allocation
|
||||
// when deserializing. We have to make sure that each chunk fits into a
|
||||
// page. So we track the chunk size in pending_chunk_ of a space, but
|
||||
// when it exceeds a page, we complete the current chunk and start a new one.
|
||||
- uint32_t pending_chunk_[kNumberOfSpaces];
|
||||
- List<uint32_t> completed_chunks_[kNumberOfSpaces];
|
||||
+ uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
|
||||
+ List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
|
||||
+ uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
|
||||
|
||||
SnapshotByteSink* sink_;
|
||||
ExternalReferenceEncoder* external_reference_encoder_;
|
||||
@@ -529,6 +534,7 @@
|
||||
CodeAddressMap* code_address_map_;
|
||||
// We map serialized large objects to indexes for back-referencing.
|
||||
uint32_t seen_large_objects_index_;
|
||||
+ uint32_t large_objects_total_size_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
commit c64b47f55237a78b6d74baa1503e7218b94811e4
|
||||
Author: yangguo <yangguo@chromium.org>
|
||||
Date: Thu Nov 20 08:20:48 2014 -0800
|
||||
|
||||
When optimizing deserialized code, make sure IC state is preserved.
|
||||
|
||||
R=jkummerow@chromium.org
|
||||
|
||||
Review URL: https://codereview.chromium.org/737373003
|
||||
|
||||
Cr-Commit-Position: refs/heads/master@{#25444}
|
||||
|
||||
diff --git a/src/compiler.cc b/src/compiler.cc
|
||||
index 3b612c1..33d88d7 100644
|
||||
--- node/deps/v8/src/compiler.cc
|
||||
+++ node/deps/v8/src/compiler.cc
|
||||
@@ -384,13 +384,21 @@
|
||||
if (FLAG_hydrogen_stats) {
|
||||
timer.Start();
|
||||
}
|
||||
- CompilationInfoWithZone unoptimized(info()->shared_info());
|
||||
+ Handle<SharedFunctionInfo> shared = info()->shared_info();
|
||||
+ CompilationInfoWithZone unoptimized(shared);
|
||||
// Note that we use the same AST that we will use for generating the
|
||||
// optimized code.
|
||||
unoptimized.SetFunction(info()->function());
|
||||
unoptimized.PrepareForCompilation(info()->scope());
|
||||
unoptimized.SetContext(info()->context());
|
||||
if (should_recompile) unoptimized.EnableDeoptimizationSupport();
|
||||
+ // If the current code has reloc info for serialization, also include
|
||||
+ // reloc info for serialization for the new code, so that deopt support
|
||||
+ // can be added without losing IC state.
|
||||
+ if (shared->code()->kind() == Code::FUNCTION &&
|
||||
+ shared->code()->has_reloc_info_for_serialization()) {
|
||||
+ unoptimized.PrepareForSerializing();
|
||||
+ }
|
||||
bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
|
||||
if (should_recompile) {
|
||||
if (!succeeded) return SetLastStatus(FAILED);
|
||||
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
|
||||
index 535dcd2..0d7363e 100644
|
||||
--- node/deps/v8/src/flag-definitions.h
|
||||
+++ node/deps/v8/src/flag-definitions.h
|
||||
@@ -427,7 +427,8 @@
|
||||
DEFINE_BOOL(trace_stub_failures, false,
|
||||
"trace deoptimization of generated code stubs")
|
||||
|
||||
-DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
|
||||
+DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts")
|
||||
+DEFINE_BOOL(serialize_inner, true, "enable caching of inner functions")
|
||||
DEFINE_BOOL(trace_code_serializer, false, "trace code serializer")
|
||||
|
||||
// compiler.cc
|
||||
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
|
||||
index e32c59f..cb8f4aa 100644
|
||||
--- node/deps/v8/src/full-codegen.cc
|
||||
+++ node/deps/v8/src/full-codegen.cc
|
||||
@@ -321,6 +321,7 @@
|
||||
cgen.PopulateDeoptimizationData(code);
|
||||
cgen.PopulateTypeFeedbackInfo(code);
|
||||
code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
|
||||
+ code->set_has_reloc_info_for_serialization(info->will_serialize());
|
||||
code->set_handler_table(*cgen.handler_table());
|
||||
code->set_compiled_optimizable(info->IsOptimizable());
|
||||
code->set_allow_osr_at_loop_nesting_level(0);
|
||||
diff --git a/src/objects-inl.h b/src/objects-inl.h
|
||||
index 3dd6fed..108f9f6 100644
|
||||
--- node/deps/v8/src/objects-inl.h
|
||||
+++ node/deps/v8/src/objects-inl.h
|
||||
@@ -4794,6 +4794,21 @@
|
||||
}
|
||||
|
||||
|
||||
+bool Code::has_reloc_info_for_serialization() {
|
||||
+ DCHECK_EQ(FUNCTION, kind());
|
||||
+ byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
|
||||
+ return FullCodeFlagsHasRelocInfoForSerialization::decode(flags);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void Code::set_has_reloc_info_for_serialization(bool value) {
|
||||
+ DCHECK_EQ(FUNCTION, kind());
|
||||
+ byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
|
||||
+ flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value);
|
||||
+ WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
|
||||
+}
|
||||
+
|
||||
+
|
||||
int Code::allow_osr_at_loop_nesting_level() {
|
||||
DCHECK_EQ(FUNCTION, kind());
|
||||
int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
|
||||
diff --git a/src/objects.h b/src/objects.h
|
||||
index 678dcb2..9569de9 100644
|
||||
--- node/deps/v8/src/objects.h
|
||||
+++ node/deps/v8/src/objects.h
|
||||
@@ -5597,6 +5597,12 @@
|
||||
inline bool is_compiled_optimizable();
|
||||
inline void set_compiled_optimizable(bool value);
|
||||
|
||||
+ // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its
|
||||
+ // reloc info includes runtime and external references to support
|
||||
+ // serialization/deserialization.
|
||||
+ inline bool has_reloc_info_for_serialization();
|
||||
+ inline void set_has_reloc_info_for_serialization(bool value);
|
||||
+
|
||||
// [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
|
||||
// how long the function has been marked for OSR and therefore which
|
||||
// level of loop nesting we are willing to do on-stack replacement
|
||||
@@ -5873,6 +5879,8 @@
|
||||
public BitField<bool, 0, 1> {}; // NOLINT
|
||||
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
|
||||
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
|
||||
+ class FullCodeFlagsHasRelocInfoForSerialization
|
||||
+ : public BitField<bool, 3, 1> {};
|
||||
|
||||
static const int kProfilerTicksOffset = kFullCodeFlags + 1;
|
||||
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
commit eb67f85439dcc273501e9fba5a9e883585505aa8
|
||||
Author: adamk <adamk@chromium.org>
|
||||
Date: Thu Dec 10 11:18:54 2015 -0800
|
||||
|
||||
Fix FuncNameInferrer usage in ParseAssignmentExpression
|
||||
|
||||
Without this fix, AssignmentExpressions that happen to be arrow functions
|
||||
would lead to unbalanced Enter/Leave calls on the fni_, causing thrashing
|
||||
while trying to infer function names. Symptoms include slow parsing
|
||||
or OOM (when we create too many AstConsStrings).
|
||||
|
||||
To try to keep this from happening in the future, added an RAII helper
|
||||
class to handle Entering/Leaving FNI state.
|
||||
|
||||
The included regression test crashes on my workstation without the patch.
|
||||
Note that it's too slow in debug mode (as well as under TurboFan),
|
||||
so I've skipped it there.
|
||||
|
||||
BUG=v8:4595
|
||||
LOG=y
|
||||
|
||||
Review URL: https://codereview.chromium.org/1507283003
|
||||
|
||||
Cr-Commit-Position: refs/heads/master@{#32768}
|
||||
|
||||
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
|
||||
index 8b077f9..1be6332 100644
|
||||
--- node/deps/v8/src/func-name-inferrer.h
|
||||
+++ node/deps/v8/src/func-name-inferrer.h
|
||||
@@ -28,21 +28,33 @@ class FunctionLiteral;
|
||||
// a name.
|
||||
class FuncNameInferrer : public ZoneObject {
|
||||
public:
|
||||
FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
|
||||
|
||||
+ // To enter function name inference state, put a FuncNameInferrer::State
|
||||
+ // on the stack.
|
||||
+ class State {
|
||||
+ public:
|
||||
+ explicit State(FuncNameInferrer* fni) : fni_(fni) {
|
||||
+ if (fni_ != nullptr) fni_->Enter();
|
||||
+ }
|
||||
+ ~State() {
|
||||
+ if (fni_ != nullptr) fni_->Leave();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ FuncNameInferrer* fni_;
|
||||
+
|
||||
+ DISALLOW_COPY_AND_ASSIGN(State);
|
||||
+ };
|
||||
+
|
||||
// Returns whether we have entered name collection state.
|
||||
bool IsOpen() const { return !entries_stack_.is_empty(); }
|
||||
|
||||
// Pushes an enclosing the name of enclosing function onto names stack.
|
||||
void PushEnclosingName(const AstRawString* name);
|
||||
|
||||
- // Enters name collection state.
|
||||
- void Enter() {
|
||||
- entries_stack_.Add(names_stack_.length(), zone());
|
||||
- }
|
||||
-
|
||||
// Pushes an encountered name onto names stack when in collection state.
|
||||
void PushLiteralName(const AstRawString* name);
|
||||
|
||||
void PushVariableName(const AstRawString* name);
|
||||
|
||||
@@ -65,18 +77,10 @@ class FuncNameInferrer : public ZoneObject {
|
||||
if (!funcs_to_infer_.is_empty()) {
|
||||
InferFunctionsNames();
|
||||
}
|
||||
}
|
||||
|
||||
- // Leaves names collection state.
|
||||
- void Leave() {
|
||||
- DCHECK(IsOpen());
|
||||
- names_stack_.Rewind(entries_stack_.RemoveLast());
|
||||
- if (entries_stack_.is_empty())
|
||||
- funcs_to_infer_.Clear();
|
||||
- }
|
||||
-
|
||||
private:
|
||||
enum NameType {
|
||||
kEnclosingConstructorName,
|
||||
kLiteralName,
|
||||
kVariableName
|
||||
@@ -85,10 +89,18 @@ class FuncNameInferrer : public ZoneObject {
|
||||
Name(const AstRawString* name, NameType type) : name(name), type(type) {}
|
||||
const AstRawString* name;
|
||||
NameType type;
|
||||
};
|
||||
|
||||
+ void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }
|
||||
+
|
||||
+ void Leave() {
|
||||
+ DCHECK(IsOpen());
|
||||
+ names_stack_.Rewind(entries_stack_.RemoveLast());
|
||||
+ if (entries_stack_.is_empty()) funcs_to_infer_.Clear();
|
||||
+ }
|
||||
+
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
// Constructs a full name in dotted notation from gathered names.
|
||||
const AstString* MakeNameFromStack();
|
||||
|
||||
diff --git a/src/parser.cc b/src/parser.cc
|
||||
index aa0ec10..b09286b 100644
|
||||
--- node/deps/v8/src/parser.cc
|
||||
+++ node/deps/v8/src/parser.cc
|
||||
@@ -2466,11 +2466,11 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
||||
|
||||
bool first_declaration = true;
|
||||
int bindings_start = peek_position();
|
||||
bool is_for_iteration_variable;
|
||||
do {
|
||||
- if (fni_ != NULL) fni_->Enter();
|
||||
+ FuncNameInferrer::State fni_state(fni_);
|
||||
|
||||
// Parse name.
|
||||
if (!first_declaration) Consume(Token::COMMA);
|
||||
|
||||
Expression* pattern;
|
||||
@@ -2541,11 +2541,10 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
||||
// Make sure that 'const x' and 'let x' initialize 'x' to undefined.
|
||||
if (value == NULL && parsing_result->descriptor.needs_init) {
|
||||
value = GetLiteralUndefined(position());
|
||||
}
|
||||
|
||||
- if (single_name && fni_ != NULL) fni_->Leave();
|
||||
parsing_result->declarations.Add(DeclarationParsingResult::Declaration(
|
||||
pattern, initializer_position, value));
|
||||
first_declaration = false;
|
||||
} while (peek() == Token::COMMA);
|
||||
|
||||
@@ -4504,11 +4503,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
|
||||
const bool has_extends = extends != nullptr;
|
||||
while (peek() != Token::RBRACE) {
|
||||
if (Check(Token::SEMICOLON)) continue;
|
||||
- if (fni_ != NULL) fni_->Enter();
|
||||
+ FuncNameInferrer::State fni_state(fni_);
|
||||
const bool in_class = true;
|
||||
const bool is_static = false;
|
||||
bool is_computed_name = false; // Classes do not care about computed
|
||||
// property names here.
|
||||
ExpressionClassifier classifier;
|
||||
@@ -4522,14 +4521,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
|
||||
DCHECK_NOT_NULL(constructor);
|
||||
} else {
|
||||
properties->Add(property, zone());
|
||||
}
|
||||
|
||||
- if (fni_ != NULL) {
|
||||
- fni_->Infer();
|
||||
- fni_->Leave();
|
||||
- }
|
||||
+ if (fni_ != NULL) fni_->Infer();
|
||||
}
|
||||
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
int end_pos = scanner()->location().end_pos;
|
||||
|
||||
diff --git a/src/preparser.h b/src/preparser.h
|
||||
index d9ef1ea..4141cd6 100644
|
||||
--- node/deps/v8/src/preparser.h
|
||||
+++ node/deps/v8/src/preparser.h
|
||||
@@ -2646,11 +2646,11 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
|
||||
ObjectLiteralChecker checker(this);
|
||||
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
|
||||
while (peek() != Token::RBRACE) {
|
||||
- if (fni_ != nullptr) fni_->Enter();
|
||||
+ FuncNameInferrer::State fni_state(fni_);
|
||||
|
||||
const bool in_class = false;
|
||||
const bool is_static = false;
|
||||
const bool has_extends = false;
|
||||
bool is_computed_name = false;
|
||||
@@ -2677,14 +2677,11 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
|
||||
if (peek() != Token::RBRACE) {
|
||||
// Need {} because of the CHECK_OK macro.
|
||||
Expect(Token::COMMA, CHECK_OK);
|
||||
}
|
||||
|
||||
- if (fni_ != nullptr) {
|
||||
- fni_->Infer();
|
||||
- fni_->Leave();
|
||||
- }
|
||||
+ if (fni_ != nullptr) fni_->Infer();
|
||||
}
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
|
||||
// Computation of literal_index must happen before pre parse bailout.
|
||||
int literal_index = function_state_->NextMaterializedLiteralIndex();
|
||||
@@ -2781,11 +2778,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
||||
|
||||
if (peek() == Token::YIELD && is_generator()) {
|
||||
return this->ParseYieldExpression(classifier, ok);
|
||||
}
|
||||
|
||||
- if (fni_ != NULL) fni_->Enter();
|
||||
+ FuncNameInferrer::State fni_state(fni_);
|
||||
ParserBase<Traits>::Checkpoint checkpoint(this);
|
||||
ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder());
|
||||
bool parenthesized_formals = peek() == Token::LPAREN;
|
||||
if (!parenthesized_formals) {
|
||||
ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
|
||||
@@ -2811,21 +2808,23 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
||||
arrow_formals_classifier.RecordDuplicateFormalParameterError(
|
||||
duplicate_loc);
|
||||
}
|
||||
expression = this->ParseArrowFunctionLiteral(
|
||||
parsing_state, arrow_formals_classifier, CHECK_OK);
|
||||
+
|
||||
+ if (fni_ != nullptr) fni_->Infer();
|
||||
+
|
||||
return expression;
|
||||
}
|
||||
|
||||
// "expression" was not itself an arrow function parameter list, but it might
|
||||
// form part of one. Propagate speculative formal parameter error locations.
|
||||
classifier->Accumulate(arrow_formals_classifier,
|
||||
ExpressionClassifier::StandardProductions |
|
||||
ExpressionClassifier::FormalParametersProductions);
|
||||
|
||||
if (!Token::IsAssignmentOp(peek())) {
|
||||
- if (fni_ != NULL) fni_->Leave();
|
||||
// Parsed conditional expression only (no assignment).
|
||||
return expression;
|
||||
}
|
||||
|
||||
if (!allow_harmony_destructuring()) {
|
||||
@@ -2871,11 +2870,10 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
||||
&& (!right->IsCall() && !right->IsCallNew())) {
|
||||
fni_->Infer();
|
||||
} else {
|
||||
fni_->RemoveLastFunction();
|
||||
}
|
||||
- fni_->Leave();
|
||||
}
|
||||
|
||||
return factory()->NewAssignment(op, expression, right, pos);
|
||||
}
|
||||
|
||||
@@ -3324,11 +3322,11 @@ ParserBase<Traits>::ParseStrongInitializationExpression(
|
||||
ExpressionClassifier* classifier, bool* ok) {
|
||||
// InitializationExpression :: (strong mode)
|
||||
// 'this' '.' IdentifierName '=' AssignmentExpression
|
||||
// 'this' '[' Expression ']' '=' AssignmentExpression
|
||||
|
||||
- if (fni_ != NULL) fni_->Enter();
|
||||
+ FuncNameInferrer::State fni_state(fni_);
|
||||
|
||||
Consume(Token::THIS);
|
||||
int pos = position();
|
||||
function_state_->set_this_location(scanner()->location());
|
||||
ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos);
|
||||
@@ -3383,11 +3381,10 @@ ParserBase<Traits>::ParseStrongInitializationExpression(
|
||||
if (!right->IsCall() && !right->IsCallNew()) {
|
||||
fni_->Infer();
|
||||
} else {
|
||||
fni_->RemoveLastFunction();
|
||||
}
|
||||
- fni_->Leave();
|
||||
}
|
||||
|
||||
if (function_state_->return_location().IsValid()) {
|
||||
ReportMessageAt(function_state_->return_location(),
|
||||
MessageTemplate::kStrongConstructorReturnMisplaced);
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -4826,10 +4826,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/** Callback function for reporting failed access checks.*/
|
||||
static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback);
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -391,10 +391,46 @@
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+bool save_serialize_toplevel;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
|
||||
+ i::FLAG_serialize_toplevel = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ i::Handle<i::HeapObject> object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ i::Script* s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
|
||||
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -196,10 +196,15 @@
|
||||
static void PrintFeatures();
|
||||
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
// Platform-dependent implementation.
|
||||
static void ProbeImpl(bool cross_compile);
|
||||
|
||||
static unsigned supported_;
|
||||
--- node/deps/v8/src/parser.cc
|
||||
+++ node/deps/v8/src/parser.cc
|
||||
@@ -4838,10 +4838,11 @@
|
||||
return !parser.failed();
|
||||
}
|
||||
|
||||
|
||||
bool Parser::Parse() {
|
||||
+ if (info()->script()->source()->IsUndefined()) return false;
|
||||
DCHECK(info()->function() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
ast_value_factory_ = info()->ast_value_factory();
|
||||
if (ast_value_factory_ == NULL) {
|
||||
ast_value_factory_ =
|
||||
--- node/deps/v8/src/serialize.cc
|
||||
+++ node/deps/v8/src/serialize.cc
|
||||
@@ -2167,11 +2167,11 @@
|
||||
payload->begin(), static_cast<size_t>(payload->length()));
|
||||
}
|
||||
|
||||
|
||||
bool SerializedCodeData::IsSane(String* source) {
|
||||
- return GetHeaderValue(kCheckSumOffset) == CheckSum(source) &&
|
||||
+ return true &&
|
||||
PayloadLength() >= SharedFunctionInfo::kSize;
|
||||
}
|
||||
|
||||
|
||||
int SerializedCodeData::CheckSum(String* string) {
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -579,11 +579,11 @@
|
||||
options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] :
|
||||
[0, 1, 2, 'ipc'];
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -202,10 +202,11 @@
|
||||
V(signal_string, "signal") \
|
||||
V(size_string, "size") \
|
||||
V(smalloc_p_string, "_smalloc_p") \
|
||||
V(sni_context_err_string, "Invalid SNI context") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
+ V(sourceless_string, "sourceless") \
|
||||
V(speed_string, "speed") \
|
||||
V(stack_string, "stack") \
|
||||
V(status_code_string, "statusCode") \
|
||||
V(status_message_string, "statusMessage") \
|
||||
V(status_string, "status") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -2957,10 +2957,11 @@
|
||||
}
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = NULL;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -3575,14 +3576,10 @@
|
||||
// Ignore SIGPIPE
|
||||
RegisterSignalHandler(SIGPIPE, SIG_IGN);
|
||||
RegisterSignalHandler(SIGINT, SignalExit, true);
|
||||
RegisterSignalHandler(SIGTERM, SignalExit, true);
|
||||
#endif // __POSIX__
|
||||
-
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
}
|
||||
|
||||
|
||||
struct AtExitCallback {
|
||||
AtExitCallback* next_;
|
||||
@@ -3761,15 +3758,10 @@
|
||||
const char* replaceInvalid = getenv("NODE_INVALID_UTF8");
|
||||
|
||||
if (replaceInvalid == NULL)
|
||||
WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;
|
||||
|
||||
-#if !defined(_WIN32)
|
||||
- // Try hard not to lose SIGUSR1 signals during the bootstrap process.
|
||||
- InstallEarlyDebugSignalHandler();
|
||||
-#endif
|
||||
-
|
||||
assert(argc > 0);
|
||||
|
||||
// Hack around with the argv pointer. Used for process.title = "blah".
|
||||
argv = uv_setup_args(argc, argv);
|
||||
|
||||
--- node/src/node.js
|
||||
+++ node/src/node.js
|
||||
@@ -65,10 +65,46 @@
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = new Buffer(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (NativeModule.exists('_third_party_main')) {
|
||||
// To allow people to extend Node in different ways, this hook allows
|
||||
// one to drop a file lib/_third_party_main.js into the build
|
||||
// directory which will be executed instead of Node's normal loading.
|
||||
process.nextTick(function() {
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -487,10 +487,11 @@
|
||||
Local<String> code = args[0]->ToString();
|
||||
Local<String> filename = GetFilenameArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
Local<Value> cached_data_buf = GetCachedData(args, 1);
|
||||
bool produce_cached_data = GetProduceCachedData(args, 1);
|
||||
+ bool sourceless = GetSourceless(args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -509,22 +510,35 @@
|
||||
if (source.GetCachedData() != NULL)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script);
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
// no 'rejected' field in cachedData
|
||||
} else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
@@ -733,10 +747,23 @@
|
||||
|
||||
return value->IsTrue();
|
||||
}
|
||||
|
||||
|
||||
+ static bool GetSourceless(
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "sourceless");
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(key);
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static bool EvalMachine(Environment* env,
|
||||
const int64_t timeout,
|
||||
const bool display_errors,
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
TryCatch& try_catch) {
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -19,10 +19,12 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
// Convert argv to to UTF8
|
||||
char** argv = new char*[argc];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
@@ -55,13 +57,80 @@
|
||||
fprintf(stderr, "Could not convert arguments to utf8.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
int main(int argc, char *argv[]) {
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef __POSIX__
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+568
@@ -0,0 +1,568 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -8137,10 +8137,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/**
|
||||
* Initializes V8. This function needs to be called before the first Isolate
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -914,10 +914,42 @@
|
||||
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -302,10 +302,15 @@
|
||||
}
|
||||
|
||||
static void PrintTarget();
|
||||
static void PrintFeatures();
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class ExternalReference;
|
||||
friend class AssemblerBase;
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -13179,10 +13179,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_positions_symbol());
|
||||
if (maybe_class_positions->IsTuple2()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
|
||||
int start_position = Smi::ToInt(class_positions->value1());
|
||||
int end_position = Smi::ToInt(class_positions->value2());
|
||||
Handle<String> script_source(
|
||||
String::cast(Script::cast(shared_info->script())->source()), isolate);
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
@@ -55,10 +56,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
source = String::Flatten(source);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -401,31 +401,46 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
|
||||
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -108,11 +108,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function _forkChild(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/internal/bootstrap/loaders.js
|
||||
+++ node/lib/internal/bootstrap/loaders.js
|
||||
@@ -337,11 +337,11 @@
|
||||
|
||||
// (code, filename, lineOffset, columnOffset
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
const script = new ContextifyScript(
|
||||
source, this.filename, 0, 0,
|
||||
- cache, false, undefined
|
||||
+ cache, false, undefined, false
|
||||
);
|
||||
|
||||
// This will be used to create code cache in tools/generate_code_cache.js
|
||||
this.script = script;
|
||||
|
||||
--- node/lib/internal/bootstrap/node.js
|
||||
+++ node/lib/internal/bootstrap/node.js
|
||||
@@ -213,10 +213,47 @@
|
||||
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
+
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (internalBinding('worker').getEnvMessagePort() !== undefined) {
|
||||
// This means we are in a Worker context, and any script execution
|
||||
// will be directed by the worker module.
|
||||
NativeModule.require('internal/worker').setupChild(evalScript);
|
||||
} else if (NativeModule.exists('_third_party_main')) {
|
||||
--- node/lib/internal/modules/cjs/loader.js
|
||||
+++ node/lib/internal/modules/cjs/loader.js
|
||||
@@ -28,14 +28,12 @@
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const path = require('path');
|
||||
const { URL } = require('url');
|
||||
-const {
|
||||
- internalModuleReadJSON,
|
||||
- internalModuleStat
|
||||
-} = process.binding('fs');
|
||||
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const { safeGetenv } = process.binding('util');
|
||||
const {
|
||||
makeRequireFunction,
|
||||
requireDepth,
|
||||
stripBOM,
|
||||
--- node/lib/vm.js
|
||||
+++ node/lib/vm.js
|
||||
@@ -55,10 +55,11 @@
|
||||
columnOffset = 0,
|
||||
cachedData,
|
||||
produceCachedData = false,
|
||||
importModuleDynamically,
|
||||
[kParsingContext]: parsingContext,
|
||||
+ sourceless = false,
|
||||
} = options;
|
||||
|
||||
if (typeof filename !== 'string') {
|
||||
throw new ERR_INVALID_ARG_TYPE('options.filename', 'string', filename);
|
||||
}
|
||||
@@ -81,11 +82,12 @@
|
||||
filename,
|
||||
lineOffset,
|
||||
columnOffset,
|
||||
cachedData,
|
||||
produceCachedData,
|
||||
- parsingContext);
|
||||
+ parsingContext,
|
||||
+ sourceless);
|
||||
} catch (e) {
|
||||
throw e; /* node-do-not-add-exception-line */
|
||||
}
|
||||
|
||||
if (importModuleDynamically !== undefined) {
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -695,12 +695,10 @@
|
||||
CHECK_EQ(0, uv_async_init(parent_env_->event_loop(),
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
start_io_thread_async.data = this;
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
}
|
||||
|
||||
bool wait_for_connect = options->wait_for_connect();
|
||||
if (parent_handle_) {
|
||||
wait_for_connect = parent_handle_->WaitForConnect();
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -2341,17 +2341,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -2361,14 +2354,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -63,10 +63,11 @@
|
||||
using v8::Symbol;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint32;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
using v8::WeakCallbackType;
|
||||
|
||||
// The vm module executes code in a sandboxed environment with a different
|
||||
@@ -629,15 +630,16 @@
|
||||
Local<Integer> line_offset;
|
||||
Local<Integer> column_offset;
|
||||
Local<Uint8Array> cached_data_buf;
|
||||
bool produce_cached_data = false;
|
||||
Local<Context> parsing_context = context;
|
||||
+ bool sourceless = false;
|
||||
|
||||
if (argc > 2) {
|
||||
// new ContextifyScript(code, filename, lineOffset, columnOffset,
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
- CHECK_EQ(argc, 7);
|
||||
+ CHECK_EQ(argc, 8);
|
||||
CHECK(args[2]->IsNumber());
|
||||
line_offset = args[2].As<Integer>();
|
||||
CHECK(args[3]->IsNumber());
|
||||
column_offset = args[3].As<Integer>();
|
||||
if (!args[4]->IsUndefined()) {
|
||||
@@ -652,10 +654,11 @@
|
||||
ContextifyContext::ContextFromContextifiedSandbox(
|
||||
env, args[6].As<Object>());
|
||||
CHECK_NOT_NULL(sandbox);
|
||||
parsing_context = sandbox->context();
|
||||
}
|
||||
+ sourceless = args[7]->IsTrue();
|
||||
} else {
|
||||
line_offset = Integer::New(isolate, 0);
|
||||
column_offset = Integer::New(isolate, 0);
|
||||
}
|
||||
|
||||
@@ -706,10 +709,14 @@
|
||||
|
||||
TryCatch try_catch(isolate);
|
||||
Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env);
|
||||
Context::Scope scope(parsing_context);
|
||||
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
isolate,
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
@@ -721,10 +728,17 @@
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
@@ -742,10 +756,15 @@
|
||||
}
|
||||
args.This()->Set(
|
||||
env->cached_data_produced_string(),
|
||||
Boolean::New(isolate, cached_data_produced));
|
||||
}
|
||||
+
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
TRACE_EVENT_NESTABLE_ASYNC_END0(
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
}
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -119,8 +121,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
--- node/src/node_options.cc
|
||||
+++ node/src/node_options.cc
|
||||
@@ -47,10 +47,11 @@
|
||||
// XXX: If you add an option here, please also add it to doc/node.1 and
|
||||
// doc/api/cli.md
|
||||
// TODO(addaleax): Make that unnecessary.
|
||||
|
||||
DebugOptionsParser::DebugOptionsParser() {
|
||||
+ return;
|
||||
#if HAVE_INSPECTOR
|
||||
AddOption("--inspect-port",
|
||||
"set host:port for inspector",
|
||||
&DebugOptions::host_port,
|
||||
kAllowedInEnvironment);
|
||||
+568
@@ -0,0 +1,568 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -8137,10 +8137,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/**
|
||||
* Initializes V8. This function needs to be called before the first Isolate
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -914,10 +914,42 @@
|
||||
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -302,10 +302,15 @@
|
||||
}
|
||||
|
||||
static void PrintTarget();
|
||||
static void PrintFeatures();
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class ExternalReference;
|
||||
friend class AssemblerBase;
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -13179,10 +13179,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_positions_symbol());
|
||||
if (maybe_class_positions->IsTuple2()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
|
||||
int start_position = Smi::ToInt(class_positions->value1());
|
||||
int end_position = Smi::ToInt(class_positions->value2());
|
||||
Handle<String> script_source(
|
||||
String::cast(Script::cast(shared_info->script())->source()), isolate);
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
@@ -55,10 +56,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
source = String::Flatten(source);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -401,31 +401,46 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
|
||||
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -108,11 +108,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function _forkChild(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/internal/bootstrap/loaders.js
|
||||
+++ node/lib/internal/bootstrap/loaders.js
|
||||
@@ -337,11 +337,11 @@
|
||||
|
||||
// (code, filename, lineOffset, columnOffset
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
const script = new ContextifyScript(
|
||||
source, this.filename, 0, 0,
|
||||
- cache, false, undefined
|
||||
+ cache, false, undefined, false
|
||||
);
|
||||
|
||||
// This will be used to create code cache in tools/generate_code_cache.js
|
||||
this.script = script;
|
||||
|
||||
--- node/lib/internal/bootstrap/node.js
|
||||
+++ node/lib/internal/bootstrap/node.js
|
||||
@@ -213,10 +213,47 @@
|
||||
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
+
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (internalBinding('worker').getEnvMessagePort() !== undefined) {
|
||||
// This means we are in a Worker context, and any script execution
|
||||
// will be directed by the worker module.
|
||||
NativeModule.require('internal/worker').setupChild(evalScript);
|
||||
} else if (NativeModule.exists('_third_party_main')) {
|
||||
--- node/lib/internal/modules/cjs/loader.js
|
||||
+++ node/lib/internal/modules/cjs/loader.js
|
||||
@@ -27,14 +27,12 @@
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const path = require('path');
|
||||
-const {
|
||||
- internalModuleReadJSON,
|
||||
- internalModuleStat
|
||||
-} = process.binding('fs');
|
||||
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const { safeGetenv } = process.binding('util');
|
||||
const {
|
||||
makeRequireFunction,
|
||||
normalizeReferrerURL,
|
||||
requireDepth,
|
||||
--- node/lib/vm.js
|
||||
+++ node/lib/vm.js
|
||||
@@ -55,10 +55,11 @@
|
||||
columnOffset = 0,
|
||||
cachedData,
|
||||
produceCachedData = false,
|
||||
importModuleDynamically,
|
||||
[kParsingContext]: parsingContext,
|
||||
+ sourceless = false,
|
||||
} = options;
|
||||
|
||||
if (typeof filename !== 'string') {
|
||||
throw new ERR_INVALID_ARG_TYPE('options.filename', 'string', filename);
|
||||
}
|
||||
@@ -84,11 +85,12 @@
|
||||
filename,
|
||||
lineOffset,
|
||||
columnOffset,
|
||||
cachedData,
|
||||
produceCachedData,
|
||||
- parsingContext);
|
||||
+ parsingContext,
|
||||
+ sourceless);
|
||||
} catch (e) {
|
||||
throw e; /* node-do-not-add-exception-line */
|
||||
}
|
||||
|
||||
if (importModuleDynamically !== undefined) {
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -705,12 +705,10 @@
|
||||
CHECK_EQ(0, uv_async_init(parent_env_->event_loop(),
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
start_io_thread_async.data = this;
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
}
|
||||
|
||||
bool wait_for_connect = options->wait_for_connect();
|
||||
if (parent_handle_) {
|
||||
wait_for_connect = parent_handle_->WaitForConnect();
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -2369,17 +2369,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -2389,14 +2382,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -63,10 +63,11 @@
|
||||
using v8::String;
|
||||
using v8::Symbol;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint32;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
using v8::WeakCallbackType;
|
||||
|
||||
// The vm module executes code in a sandboxed environment with a different
|
||||
@@ -638,15 +639,16 @@
|
||||
Local<Integer> line_offset;
|
||||
Local<Integer> column_offset;
|
||||
Local<ArrayBufferView> cached_data_buf;
|
||||
bool produce_cached_data = false;
|
||||
Local<Context> parsing_context = context;
|
||||
+ bool sourceless = false;
|
||||
|
||||
if (argc > 2) {
|
||||
// new ContextifyScript(code, filename, lineOffset, columnOffset,
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
- CHECK_EQ(argc, 7);
|
||||
+ CHECK_EQ(argc, 8);
|
||||
CHECK(args[2]->IsNumber());
|
||||
line_offset = args[2].As<Integer>();
|
||||
CHECK(args[3]->IsNumber());
|
||||
column_offset = args[3].As<Integer>();
|
||||
if (!args[4]->IsUndefined()) {
|
||||
@@ -661,10 +663,11 @@
|
||||
ContextifyContext::ContextFromContextifiedSandbox(
|
||||
env, args[6].As<Object>());
|
||||
CHECK_NOT_NULL(sandbox);
|
||||
parsing_context = sandbox->context();
|
||||
}
|
||||
+ sourceless = args[7]->IsTrue();
|
||||
} else {
|
||||
line_offset = Integer::New(isolate, 0);
|
||||
column_offset = Integer::New(isolate, 0);
|
||||
}
|
||||
|
||||
@@ -715,10 +718,14 @@
|
||||
|
||||
TryCatch try_catch(isolate);
|
||||
Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env);
|
||||
Context::Scope scope(parsing_context);
|
||||
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
isolate,
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
@@ -730,10 +737,17 @@
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
@@ -751,10 +765,15 @@
|
||||
}
|
||||
args.This()->Set(
|
||||
env->cached_data_produced_string(),
|
||||
Boolean::New(isolate, cached_data_produced));
|
||||
}
|
||||
+
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
TRACE_EVENT_NESTABLE_ASYNC_END0(
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
}
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -119,8 +121,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
--- node/src/node_options.cc
|
||||
+++ node/src/node_options.cc
|
||||
@@ -55,10 +55,11 @@
|
||||
// XXX: If you add an option here, please also add it to doc/node.1 and
|
||||
// doc/api/cli.md
|
||||
// TODO(addaleax): Make that unnecessary.
|
||||
|
||||
DebugOptionsParser::DebugOptionsParser() {
|
||||
+ return;
|
||||
#if HAVE_INSPECTOR
|
||||
AddOption("--inspect-port",
|
||||
"set host:port for inspector",
|
||||
&DebugOptions::host_port,
|
||||
kAllowedInEnvironment);
|
||||
+616
@@ -0,0 +1,616 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -8826,10 +8826,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/**
|
||||
* Initializes V8. This function needs to be called before the first Isolate
|
||||
--- node/deps/v8/src/api/api.cc
|
||||
+++ node/deps/v8/src/api/api.cc
|
||||
@@ -902,10 +902,38 @@
|
||||
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
+
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto function_info =
|
||||
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
|
||||
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
|
||||
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
|
||||
|
||||
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
|
||||
: extension_(std::move(extension)) {}
|
||||
|
||||
--- node/deps/v8/src/codegen/compiler.cc
|
||||
+++ node/deps/v8/src/codegen/compiler.cc
|
||||
@@ -2001,11 +2001,11 @@
|
||||
// First check per-isolate compilation cache.
|
||||
maybe_result = compilation_cache->LookupScript(
|
||||
source, script_details.name_obj, script_details.line_offset,
|
||||
script_details.column_offset, origin_options, isolate->native_context(),
|
||||
language_mode);
|
||||
- if (!maybe_result.is_null()) {
|
||||
+ if (!maybe_result.is_null() && source_length) {
|
||||
compile_timer.set_hit_isolate_cache();
|
||||
} else if (can_consume_code_cache) {
|
||||
compile_timer.set_consuming_code_cache();
|
||||
// Then check cached code provided by embedder.
|
||||
HistogramTimerScope timer(isolate->counters()->compile_deserialize());
|
||||
--- node/deps/v8/src/objects/js-objects.cc
|
||||
+++ node/deps/v8/src/objects/js-objects.cc
|
||||
@@ -5470,10 +5470,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_positions_symbol());
|
||||
if (maybe_class_positions->IsClassPositions()) {
|
||||
+ if (String::cast(Script::cast(shared_info->script()).source())->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
ClassPositions class_positions =
|
||||
ClassPositions::cast(*maybe_class_positions);
|
||||
int start_position = class_positions.start();
|
||||
int end_position = class_positions.end();
|
||||
Handle<String> script_source(
|
||||
--- node/deps/v8/src/objects/shared-function-info-inl.h
|
||||
+++ node/deps/v8/src/objects/shared-function-info-inl.h
|
||||
@@ -502,10 +502,18 @@
|
||||
// check if it is old. Note, this is done this way since this function can be
|
||||
// called by the concurrent marker.
|
||||
Object data = function_data();
|
||||
if (!data.IsBytecodeArray()) return false;
|
||||
|
||||
+ Object script_obj = script();
|
||||
+ if (!script_obj.IsUndefined()) {
|
||||
+ Script script = Script::cast(script_obj);
|
||||
+ if (script.source().IsUndefined()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (mode == BytecodeFlushMode::kStressFlushBytecode) return true;
|
||||
|
||||
BytecodeArray bytecode = BytecodeArray::cast(data);
|
||||
|
||||
return bytecode.IsOld();
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -19,10 +19,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (String::cast(info->script()->source())->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
@@ -55,10 +56,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (String::cast(info->script()->source())->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
std::unique_ptr<Utf16CharacterStream> stream(
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -401,26 +401,39 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != kMagicNumber) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksumPartAOffset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksumPartBOffset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ // base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(ChecksummedContent()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(ChecksummedContent()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source,
|
||||
ScriptOriginOptions origin_options) {
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -103,11 +103,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return module.exports.spawn(options.execPath, args, options);
|
||||
}
|
||||
|
||||
function _forkChild(fd) {
|
||||
// set process.send()
|
||||
const p = new Pipe(PipeConstants.IPC);
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ node/lib/internal/bootstrap/pkg.js
|
||||
@@ -0,0 +1,44 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const {
|
||||
+ prepareMainThreadExecution
|
||||
+} = require('internal/bootstrap/pre_execution');
|
||||
+
|
||||
+prepareMainThreadExecution(true);
|
||||
+
|
||||
+(function () {
|
||||
+ var __require__ = require;
|
||||
+ var fs = __require__('fs');
|
||||
+ var vm = __require__('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, __require__,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+}());
|
||||
--- node/lib/internal/bootstrap/pre_execution.js
|
||||
+++ node/lib/internal/bootstrap/pre_execution.js
|
||||
@@ -4,11 +4,16 @@
|
||||
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const { Buffer } = require('buffer');
|
||||
const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes;
|
||||
|
||||
+let _alreadyPrepared = false;
|
||||
+
|
||||
function prepareMainThreadExecution(expandArgv1 = false) {
|
||||
+ if (_alreadyPrepared === true) return;
|
||||
+ _alreadyPrepared = true;
|
||||
+
|
||||
// Patch the process object with legacy properties and normalizations
|
||||
patchProcessObject(expandArgv1);
|
||||
setupTraceCategoryState();
|
||||
setupInspectorHooks();
|
||||
setupWarningHandler();
|
||||
@@ -75,11 +80,11 @@
|
||||
configurable: false,
|
||||
value: process.argv[0]
|
||||
});
|
||||
process.argv[0] = process.execPath;
|
||||
|
||||
- if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-')) {
|
||||
+ if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-') && process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
|
||||
// Expand process.argv[1] into a full path.
|
||||
const path = require('path');
|
||||
process.argv[1] = path.resolve(process.argv[1]);
|
||||
}
|
||||
|
||||
--- node/lib/internal/modules/cjs/loader.js
|
||||
+++ node/lib/internal/modules/cjs/loader.js
|
||||
@@ -40,14 +40,12 @@
|
||||
const vm = require('vm');
|
||||
const assert = require('internal/assert');
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const path = require('path');
|
||||
-const {
|
||||
- internalModuleReadJSON,
|
||||
- internalModuleStat
|
||||
-} = internalBinding('fs');
|
||||
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const { safeGetenv } = internalBinding('credentials');
|
||||
const {
|
||||
makeRequireFunction,
|
||||
normalizeReferrerURL,
|
||||
stripBOM,
|
||||
--- node/lib/vm.js
|
||||
+++ node/lib/vm.js
|
||||
@@ -58,10 +58,11 @@
|
||||
columnOffset = 0,
|
||||
cachedData,
|
||||
produceCachedData = false,
|
||||
importModuleDynamically,
|
||||
[kParsingContext]: parsingContext,
|
||||
+ sourceless = false,
|
||||
} = options;
|
||||
|
||||
validateString(filename, 'options.filename');
|
||||
validateInt32(lineOffset, 'options.lineOffset');
|
||||
validateInt32(columnOffset, 'options.columnOffset');
|
||||
@@ -85,11 +86,12 @@
|
||||
filename,
|
||||
lineOffset,
|
||||
columnOffset,
|
||||
cachedData,
|
||||
produceCachedData,
|
||||
- parsingContext);
|
||||
+ parsingContext,
|
||||
+ sourceless);
|
||||
} catch (e) {
|
||||
throw e; /* node-do-not-add-exception-line */
|
||||
}
|
||||
|
||||
if (importModuleDynamically !== undefined) {
|
||||
--- node/node.gyp
|
||||
+++ node/node.gyp
|
||||
@@ -26,10 +26,11 @@
|
||||
'node_intermediate_lib_type%': 'static_library',
|
||||
'library_files': [
|
||||
'lib/internal/bootstrap/environment.js',
|
||||
'lib/internal/bootstrap/loaders.js',
|
||||
'lib/internal/bootstrap/node.js',
|
||||
+ 'lib/internal/bootstrap/pkg.js',
|
||||
'lib/internal/bootstrap/pre_execution.js',
|
||||
'lib/internal/per_context/primordials.js',
|
||||
'lib/internal/per_context/domexception.js',
|
||||
'lib/async_hooks.js',
|
||||
'lib/assert.js',
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -772,12 +772,10 @@
|
||||
CHECK_EQ(0, uv_async_init(parent_env_->event_loop(),
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
start_io_thread_async.data = this;
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
}
|
||||
|
||||
bool wait_for_connect = options.wait_for_connect();
|
||||
if (parent_handle_) {
|
||||
wait_for_connect = parent_handle_->WaitForConnect();
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -367,10 +367,12 @@
|
||||
CHECK(req_wrap_queue()->IsEmpty());
|
||||
CHECK(handle_wrap_queue()->IsEmpty());
|
||||
|
||||
set_has_run_bootstrapping_code(true);
|
||||
|
||||
+ USE(StartExecution(this, "internal/bootstrap/pkg"));
|
||||
+
|
||||
return scope.Escape(result);
|
||||
}
|
||||
|
||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
@@ -495,17 +497,10 @@
|
||||
#endif // __POSIX__
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (auto& s : stdio) {
|
||||
const int fd = &s - stdio;
|
||||
if (fstat(fd, &s.stat) == 0)
|
||||
continue;
|
||||
@@ -517,14 +512,10 @@
|
||||
ABORT();
|
||||
if (fstat(fd, &s.stat) != 0)
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -67,10 +67,11 @@
|
||||
using v8::ScriptOrigin;
|
||||
using v8::ScriptOrModule;
|
||||
using v8::String;
|
||||
using v8::Uint32;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
using v8::WeakCallbackType;
|
||||
|
||||
// The vm module executes code in a sandboxed environment with a different
|
||||
@@ -652,15 +653,16 @@
|
||||
Local<Integer> line_offset;
|
||||
Local<Integer> column_offset;
|
||||
Local<ArrayBufferView> cached_data_buf;
|
||||
bool produce_cached_data = false;
|
||||
Local<Context> parsing_context = context;
|
||||
+ bool sourceless = false;
|
||||
|
||||
if (argc > 2) {
|
||||
// new ContextifyScript(code, filename, lineOffset, columnOffset,
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
- CHECK_EQ(argc, 7);
|
||||
+ CHECK_EQ(argc, 8);
|
||||
CHECK(args[2]->IsNumber());
|
||||
line_offset = args[2].As<Integer>();
|
||||
CHECK(args[3]->IsNumber());
|
||||
column_offset = args[3].As<Integer>();
|
||||
if (!args[4]->IsUndefined()) {
|
||||
@@ -675,10 +677,11 @@
|
||||
ContextifyContext::ContextFromContextifiedSandbox(
|
||||
env, args[6].As<Object>());
|
||||
CHECK_NOT_NULL(sandbox);
|
||||
parsing_context = sandbox->context();
|
||||
}
|
||||
+ sourceless = args[7]->IsTrue();
|
||||
} else {
|
||||
line_offset = Integer::New(isolate, 0);
|
||||
column_offset = Integer::New(isolate, 0);
|
||||
}
|
||||
|
||||
@@ -729,10 +732,14 @@
|
||||
|
||||
TryCatchScope try_catch(env);
|
||||
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
|
||||
Context::Scope scope(parsing_context);
|
||||
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
isolate,
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
@@ -745,10 +752,17 @@
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->context(),
|
||||
@@ -770,10 +784,15 @@
|
||||
args.This()->Set(
|
||||
env->context(),
|
||||
env->cached_data_produced_string(),
|
||||
Boolean::New(isolate, cached_data_produced)).Check();
|
||||
}
|
||||
+
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
TRACE_EVENT_NESTABLE_ASYNC_END0(
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
}
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <cstdio>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -121,8 +123,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
--- node/src/node_options.cc
|
||||
+++ node/src/node_options.cc
|
||||
@@ -279,10 +279,11 @@
|
||||
// XXX: If you add an option here, please also add it to doc/node.1 and
|
||||
// doc/api/cli.md
|
||||
// TODO(addaleax): Make that unnecessary.
|
||||
|
||||
DebugOptionsParser::DebugOptionsParser() {
|
||||
+ return;
|
||||
AddOption("--inspect-port",
|
||||
"set host:port for inspector",
|
||||
&DebugOptions::host_port,
|
||||
kAllowedInEnvironment);
|
||||
AddAlias("--debug-port", "--inspect-port");
|
||||
+580
@@ -0,0 +1,580 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -8662,10 +8662,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/**
|
||||
* Initializes V8. This function needs to be called before the first Isolate
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -894,10 +894,38 @@
|
||||
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
+
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto function_info =
|
||||
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
|
||||
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
|
||||
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
|
||||
|
||||
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
|
||||
: extension_(std::move(extension)) {}
|
||||
|
||||
--- node/deps/v8/src/objects/js-objects.cc
|
||||
+++ node/deps/v8/src/objects/js-objects.cc
|
||||
@@ -5407,10 +5407,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_positions_symbol());
|
||||
if (maybe_class_positions->IsClassPositions()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
ClassPositions class_positions =
|
||||
ClassPositions::cast(*maybe_class_positions);
|
||||
int start_position = class_positions->start();
|
||||
int end_position = class_positions->end();
|
||||
Handle<String> script_source(
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -19,10 +19,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
@@ -55,10 +56,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()), isolate);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
std::unique_ptr<Utf16CharacterStream> stream(
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -340,26 +340,39 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != kMagicNumber) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksumPartAOffset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksumPartBOffset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ // base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(ChecksummedContent()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(ChecksummedContent()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source,
|
||||
ScriptOriginOptions origin_options) {
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -115,11 +115,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function _forkChild(fd) {
|
||||
// set process.send()
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ node/lib/internal/bootstrap/pkg.js
|
||||
@@ -0,0 +1,44 @@
|
||||
+'use strict';
|
||||
+
|
||||
+const {
|
||||
+ prepareMainThreadExecution
|
||||
+} = require('internal/bootstrap/pre_execution');
|
||||
+
|
||||
+prepareMainThreadExecution(true);
|
||||
+
|
||||
+(function () {
|
||||
+ var __require__ = require;
|
||||
+ var fs = __require__('fs');
|
||||
+ var vm = __require__('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, __require__,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+}());
|
||||
--- node/lib/internal/bootstrap/pre_execution.js
|
||||
+++ node/lib/internal/bootstrap/pre_execution.js
|
||||
@@ -3,11 +3,16 @@
|
||||
const { Object, SafeWeakMap } = primordials;
|
||||
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const { Buffer } = require('buffer');
|
||||
|
||||
+let _alreadyPrepared = false;
|
||||
+
|
||||
function prepareMainThreadExecution(expandArgv1 = false) {
|
||||
+ if (_alreadyPrepared === true) return;
|
||||
+ _alreadyPrepared = true;
|
||||
+
|
||||
// Patch the process object with legacy properties and normalizations
|
||||
patchProcessObject(expandArgv1);
|
||||
setupTraceCategoryState();
|
||||
setupInspectorHooks();
|
||||
setupWarningHandler();
|
||||
@@ -65,11 +70,11 @@
|
||||
configurable: false,
|
||||
value: process.argv[0]
|
||||
});
|
||||
process.argv[0] = process.execPath;
|
||||
|
||||
- if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-')) {
|
||||
+ if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-') && process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
|
||||
// Expand process.argv[1] into a full path.
|
||||
const path = require('path');
|
||||
process.argv[1] = path.resolve(process.argv[1]);
|
||||
}
|
||||
|
||||
--- node/lib/internal/modules/cjs/loader.js
|
||||
+++ node/lib/internal/modules/cjs/loader.js
|
||||
@@ -29,14 +29,12 @@
|
||||
const vm = require('vm');
|
||||
const assert = require('internal/assert');
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const path = require('path');
|
||||
-const {
|
||||
- internalModuleReadJSON,
|
||||
- internalModuleStat
|
||||
-} = internalBinding('fs');
|
||||
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const { safeGetenv } = internalBinding('credentials');
|
||||
const {
|
||||
makeRequireFunction,
|
||||
normalizeReferrerURL,
|
||||
stripBOM,
|
||||
--- node/lib/vm.js
|
||||
+++ node/lib/vm.js
|
||||
@@ -57,10 +57,11 @@
|
||||
columnOffset = 0,
|
||||
cachedData,
|
||||
produceCachedData = false,
|
||||
importModuleDynamically,
|
||||
[kParsingContext]: parsingContext,
|
||||
+ sourceless = false,
|
||||
} = options;
|
||||
|
||||
validateString(filename, 'options.filename');
|
||||
validateInt32(lineOffset, 'options.lineOffset');
|
||||
validateInt32(columnOffset, 'options.columnOffset');
|
||||
@@ -84,11 +85,12 @@
|
||||
filename,
|
||||
lineOffset,
|
||||
columnOffset,
|
||||
cachedData,
|
||||
produceCachedData,
|
||||
- parsingContext);
|
||||
+ parsingContext,
|
||||
+ sourceless);
|
||||
} catch (e) {
|
||||
throw e; /* node-do-not-add-exception-line */
|
||||
}
|
||||
|
||||
if (importModuleDynamically !== undefined) {
|
||||
--- node/node.gyp
|
||||
+++ node/node.gyp
|
||||
@@ -27,10 +27,11 @@
|
||||
'node_intermediate_lib_type%': 'static_library',
|
||||
'library_files': [
|
||||
'lib/internal/bootstrap/environment.js',
|
||||
'lib/internal/bootstrap/loaders.js',
|
||||
'lib/internal/bootstrap/node.js',
|
||||
+ 'lib/internal/bootstrap/pkg.js',
|
||||
'lib/internal/bootstrap/pre_execution.js',
|
||||
'lib/internal/per_context/primordials.js',
|
||||
'lib/internal/per_context/setup.js',
|
||||
'lib/internal/per_context/domexception.js',
|
||||
'lib/async_hooks.js',
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -716,12 +716,10 @@
|
||||
CHECK_EQ(0, uv_async_init(parent_env_->event_loop(),
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
start_io_thread_async.data = this;
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
}
|
||||
|
||||
bool wait_for_connect = options.wait_for_connect();
|
||||
if (parent_handle_) {
|
||||
wait_for_connect = parent_handle_->WaitForConnect();
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -335,10 +335,12 @@
|
||||
CHECK(env->req_wrap_queue()->IsEmpty());
|
||||
CHECK(env->handle_wrap_queue()->IsEmpty());
|
||||
|
||||
env->set_has_run_bootstrapping_code(true);
|
||||
|
||||
+ USE(StartExecution(env, "internal/bootstrap/pkg"));
|
||||
+
|
||||
return scope.EscapeMaybe(result);
|
||||
}
|
||||
|
||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
@@ -453,17 +455,10 @@
|
||||
|
||||
#endif // __POSIX__
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -473,14 +468,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -65,10 +65,11 @@
|
||||
using v8::ScriptOrigin;
|
||||
using v8::String;
|
||||
using v8::Symbol;
|
||||
using v8::Uint32;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
using v8::WeakCallbackType;
|
||||
|
||||
// The vm module executes code in a sandboxed environment with a different
|
||||
@@ -643,15 +644,16 @@
|
||||
Local<Integer> line_offset;
|
||||
Local<Integer> column_offset;
|
||||
Local<ArrayBufferView> cached_data_buf;
|
||||
bool produce_cached_data = false;
|
||||
Local<Context> parsing_context = context;
|
||||
+ bool sourceless = false;
|
||||
|
||||
if (argc > 2) {
|
||||
// new ContextifyScript(code, filename, lineOffset, columnOffset,
|
||||
// cachedData, produceCachedData, parsingContext)
|
||||
- CHECK_EQ(argc, 7);
|
||||
+ CHECK_EQ(argc, 8);
|
||||
CHECK(args[2]->IsNumber());
|
||||
line_offset = args[2].As<Integer>();
|
||||
CHECK(args[3]->IsNumber());
|
||||
column_offset = args[3].As<Integer>();
|
||||
if (!args[4]->IsUndefined()) {
|
||||
@@ -666,10 +668,11 @@
|
||||
ContextifyContext::ContextFromContextifiedSandbox(
|
||||
env, args[6].As<Object>());
|
||||
CHECK_NOT_NULL(sandbox);
|
||||
parsing_context = sandbox->context();
|
||||
}
|
||||
+ sourceless = args[7]->IsTrue();
|
||||
} else {
|
||||
line_offset = Integer::New(isolate, 0);
|
||||
column_offset = Integer::New(isolate, 0);
|
||||
}
|
||||
|
||||
@@ -720,10 +723,14 @@
|
||||
|
||||
TryCatchScope try_catch(env);
|
||||
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
|
||||
Context::Scope scope(parsing_context);
|
||||
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
isolate,
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
@@ -736,10 +743,17 @@
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->context(),
|
||||
@@ -761,10 +775,15 @@
|
||||
args.This()->Set(
|
||||
env->context(),
|
||||
env->cached_data_produced_string(),
|
||||
Boolean::New(isolate, cached_data_produced)).Check();
|
||||
}
|
||||
+
|
||||
+ if (sourceless && produce_cached_data) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
TRACE_EVENT_NESTABLE_ASYNC_END0(
|
||||
TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
contextify_script);
|
||||
}
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <cstdio>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -121,8 +123,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
--- node/src/node_options.cc
|
||||
+++ node/src/node_options.cc
|
||||
@@ -232,10 +232,11 @@
|
||||
// XXX: If you add an option here, please also add it to doc/node.1 and
|
||||
// doc/api/cli.md
|
||||
// TODO(addaleax): Make that unnecessary.
|
||||
|
||||
DebugOptionsParser::DebugOptionsParser() {
|
||||
+ return;
|
||||
AddOption("--inspect-port",
|
||||
"set host:port for inspector",
|
||||
&DebugOptions::host_port,
|
||||
kAllowedInEnvironment);
|
||||
AddAlias("--debug-port", "--inspect-port");
|
||||
+490
@@ -0,0 +1,490 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -6065,10 +6065,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/** Callback function for reporting failed access checks.*/
|
||||
V8_INLINE static V8_DEPRECATE_SOON(
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -428,10 +428,46 @@
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+bool save_serialize_toplevel;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
|
||||
+ i::FLAG_serialize_toplevel = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
|
||||
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -223,10 +223,15 @@
|
||||
static void PrintFeatures();
|
||||
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
// Platform-dependent implementation.
|
||||
static void ProbeImpl(bool cross_compile);
|
||||
|
||||
static unsigned supported_;
|
||||
--- node/deps/v8/src/parser.cc
|
||||
+++ node/deps/v8/src/parser.cc
|
||||
@@ -5636,10 +5636,11 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Parser::Parse(ParseInfo* info) {
|
||||
+ if (info->script()->source()->IsUndefined()) return false;
|
||||
DCHECK(info->function() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
// Ok to use Isolate here; this function is only called in the main thread.
|
||||
DCHECK(parsing_on_main_thread_);
|
||||
Isolate* isolate = info->isolate();
|
||||
--- node/deps/v8/src/runtime/runtime-classes.cc
|
||||
+++ node/deps/v8/src/runtime/runtime-classes.cc
|
||||
@@ -236,10 +236,14 @@
|
||||
if (!start_position->IsSmi() || !end_position->IsSmi() ||
|
||||
!Handle<Script>::cast(script)->HasValidSource()) {
|
||||
return isolate->ThrowIllegalOperation();
|
||||
}
|
||||
|
||||
+ if (Handle<Script>::cast(script)->source()->IsUndefined()) {
|
||||
+ return *isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
+
|
||||
Handle<String> source(String::cast(Handle<Script>::cast(script)->source()));
|
||||
return *isolate->factory()->NewSubString(
|
||||
source, Handle<Smi>::cast(start_position)->value(),
|
||||
Handle<Smi>::cast(end_position)->value());
|
||||
}
|
||||
--- node/deps/v8/src/snapshot/serialize.cc
|
||||
+++ node/deps/v8/src/snapshot/serialize.cc
|
||||
@@ -2695,24 +2695,36 @@
|
||||
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, String* source) const {
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != SourceHash(source)) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
- if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(Payload()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// Return ScriptData object and relinquish ownership over it to the caller.
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -49,11 +49,11 @@
|
||||
options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] :
|
||||
[0, 1, 2, 'ipc'];
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/module.js
|
||||
+++ node/lib/module.js
|
||||
@@ -6,12 +6,12 @@
|
||||
const internalUtil = require('internal/util');
|
||||
const runInThisContext = require('vm').runInThisContext;
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
|
||||
-const internalModuleStat = process.binding('fs').internalModuleStat;
|
||||
+const internalModuleReadFile = function (f) { return require('fs').internalModuleReadFile(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
|
||||
const splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
|
||||
const isIndexRe = /^index\.\w+?$/;
|
||||
const shebangRe = /^\#\!.*/;
|
||||
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -197,10 +197,11 @@
|
||||
V(session_id_string, "sessionId") \
|
||||
V(signal_string, "signal") \
|
||||
V(size_string, "size") \
|
||||
V(sni_context_err_string, "Invalid SNI context") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
+ V(sourceless_string, "sourceless") \
|
||||
V(speed_string, "speed") \
|
||||
V(stack_string, "stack") \
|
||||
V(status_string, "status") \
|
||||
V(stdio_string, "stdio") \
|
||||
V(subject_string, "subject") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3319,10 +3319,11 @@
|
||||
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = nullptr;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -3934,15 +3935,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -3952,12 +3948,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
- CHECK_EQ(err, 0);
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
@@ -4098,14 +4092,10 @@
|
||||
// is to prevent memory pointers from being moved around that are returned by
|
||||
// Buffer::Data().
|
||||
const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
|
||||
V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
|
||||
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
-
|
||||
// We should set node_is_initialized here instead of in node::Start,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
}
|
||||
--- node/src/node.js
|
||||
+++ node/src/node.js
|
||||
@@ -52,10 +52,46 @@
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = new Buffer(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (NativeModule.exists('_third_party_main')) {
|
||||
// To allow people to extend Node in different ways, this hook allows
|
||||
// one to drop a file lib/_third_party_main.js into the build
|
||||
// directory which will be executed instead of Node's normal loading.
|
||||
process.nextTick(function() {
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -478,10 +478,11 @@
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
MaybeLocal<Value> cached_data_buf = GetCachedData(env, args, 1);
|
||||
bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
+ bool sourceless = GetSourceless(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -501,22 +502,37 @@
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(env->isolate(),
|
||||
v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
@@ -723,10 +739,24 @@
|
||||
|
||||
return value->IsTrue();
|
||||
}
|
||||
|
||||
|
||||
+ static bool GetSourceless(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->sourceless_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "node.h"
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
// Convert argv to to UTF8
|
||||
char** argv = new char*[argc + 1];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
@@ -35,17 +37,84 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
int main(int argc, char *argv[]) {
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+514
@@ -0,0 +1,514 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -6429,10 +6429,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/** Callback function for reporting failed access checks.*/
|
||||
V8_INLINE static V8_DEPRECATED(
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -547,10 +547,46 @@
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+bool save_serialize_toplevel;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
|
||||
+ i::FLAG_serialize_toplevel = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
|
||||
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -235,10 +235,15 @@
|
||||
}
|
||||
|
||||
static void PrintTarget();
|
||||
static void PrintFeatures();
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class ExternalReference;
|
||||
friend class AssemblerBase;
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -13396,10 +13396,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> class_start_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_start_position_symbol());
|
||||
if (class_start_position->IsSmi()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined()) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
Handle<Object> class_end_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_end_position_symbol());
|
||||
Handle<String> script_source(
|
||||
String::cast(Script::cast(shared_info->script())->source()), isolate);
|
||||
return isolate->factory()->NewSubString(
|
||||
--- node/deps/v8/src/parsing/parser.cc
|
||||
+++ node/deps/v8/src/parsing/parser.cc
|
||||
@@ -5057,10 +5057,11 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Parser::Parse(ParseInfo* info) {
|
||||
+ if (info->script()->source()->IsUndefined()) return false;
|
||||
DCHECK(info->literal() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
// Ok to use Isolate here; this function is only called in the main thread.
|
||||
DCHECK(parsing_on_main_thread_);
|
||||
Isolate* isolate = info->isolate();
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -342,24 +342,36 @@
|
||||
}
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, String* source) const {
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != SourceHash(source)) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
- if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(Payload()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(String* source) const {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -54,11 +54,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/internal/bootstrap_node.js
|
||||
+++ node/lib/internal/bootstrap_node.js
|
||||
@@ -83,10 +83,46 @@
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = new Buffer(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (NativeModule.exists('_third_party_main')) {
|
||||
// To allow people to extend Node in different ways, this hook allows
|
||||
// one to drop a file lib/_third_party_main.js into the build
|
||||
// directory which will be executed instead of Node's normal loading.
|
||||
process.nextTick(function() {
|
||||
--- node/lib/module.js
|
||||
+++ node/lib/module.js
|
||||
@@ -6,12 +6,12 @@
|
||||
const internalUtil = require('internal/util');
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
|
||||
-const internalModuleStat = process.binding('fs').internalModuleStat;
|
||||
+const internalModuleReadFile = function (f) { return require('fs').internalModuleReadFile(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
|
||||
|
||||
// If obj.hasOwnProperty has been overridden, then calling
|
||||
// obj.hasOwnProperty(prop) will break.
|
||||
// See: https://github.com/joyent/node/issues/1707
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -192,10 +192,11 @@
|
||||
V(shell_string, "shell") \
|
||||
V(signal_string, "signal") \
|
||||
V(size_string, "size") \
|
||||
V(sni_context_err_string, "Invalid SNI context") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
+ V(sourceless_string, "sourceless") \
|
||||
V(speed_string, "speed") \
|
||||
V(stack_string, "stack") \
|
||||
V(status_string, "status") \
|
||||
V(stdio_string, "stdio") \
|
||||
V(subject_string, "subject") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3621,10 +3621,11 @@
|
||||
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = nullptr;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -4435,15 +4436,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -4453,12 +4449,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
- CHECK_EQ(err, 0);
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
@@ -4637,14 +4631,10 @@
|
||||
// is to prevent memory pointers from being moved around that are returned by
|
||||
// Buffer::Data().
|
||||
const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
|
||||
V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
|
||||
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
-
|
||||
// We should set node_is_initialized here instead of in node::Start,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
}
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -38,10 +38,11 @@
|
||||
using v8::ScriptOrigin;
|
||||
using v8::String;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
|
||||
|
||||
class ContextifyContext {
|
||||
@@ -499,17 +500,19 @@
|
||||
MaybeLocal<Integer> lineOffset = GetLineOffsetArg(env, options);
|
||||
MaybeLocal<Integer> columnOffset = GetColumnOffsetArg(env, options);
|
||||
Maybe<bool> maybe_display_errors = GetDisplayErrorsArg(env, options);
|
||||
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, options);
|
||||
Maybe<bool> maybe_produce_cached_data = GetProduceCachedData(env, options);
|
||||
+ Maybe<bool> maybe_sourceless = GetSourceless(env, options);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
bool display_errors = maybe_display_errors.FromJust();
|
||||
bool produce_cached_data = maybe_produce_cached_data.FromJust();
|
||||
+ bool sourceless = maybe_sourceless.FromJust();
|
||||
|
||||
ScriptCompiler::CachedData* cached_data = nullptr;
|
||||
if (!cached_data_buf.IsEmpty()) {
|
||||
Local<Uint8Array> ui8 = cached_data_buf.ToLocalChecked();
|
||||
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
|
||||
@@ -527,22 +530,37 @@
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
DecorateErrorStack(env, try_catch);
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(env->isolate(),
|
||||
v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
@@ -836,10 +854,27 @@
|
||||
Local<Value> value = maybe_value.ToLocalChecked();
|
||||
return Just(value->IsTrue());
|
||||
}
|
||||
|
||||
|
||||
+ static Maybe<bool> GetSourceless(Environment* env, Local<Value> options) {
|
||||
+ if (!options->IsObject()) {
|
||||
+ return Just(false);
|
||||
+ }
|
||||
+
|
||||
+ MaybeLocal<Value> maybe_value =
|
||||
+ options.As<Object>()->Get(env->context(),
|
||||
+ env->sourceless_string());
|
||||
+
|
||||
+ if (maybe_value.IsEmpty())
|
||||
+ return Nothing<bool>();
|
||||
+
|
||||
+ Local<Value> value = maybe_value.ToLocalChecked();
|
||||
+ return Just(value->IsTrue());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static MaybeLocal<Integer> GetLineOffsetArg(Environment* env,
|
||||
Local<Value> options) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(env->isolate(), 0);
|
||||
|
||||
if (!options->IsObject()) {
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "node.h"
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
@@ -44,17 +46,86 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
int main(int argc, char *argv[]) {
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -7911,10 +7911,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/** Callback function for reporting failed access checks.*/
|
||||
V8_INLINE static V8_DEPRECATED(
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -830,10 +830,46 @@
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+bool save_serialize_toplevel;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
|
||||
+ i::FLAG_serialize_toplevel = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
|
||||
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -297,10 +297,15 @@
|
||||
}
|
||||
|
||||
static void PrintTarget();
|
||||
static void PrintFeatures();
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class ExternalReference;
|
||||
friend class AssemblerBase;
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -13206,10 +13206,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> class_start_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_start_position_symbol());
|
||||
if (class_start_position->IsSmi()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
Handle<Object> class_end_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_end_position_symbol());
|
||||
Handle<String> script_source(
|
||||
String::cast(Script::cast(shared_info->script())->source()), isolate);
|
||||
return isolate->factory()->NewSubString(
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
@@ -52,10 +53,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
source = String::Flatten(source);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -392,31 +392,46 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
|
||||
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -104,11 +104,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/internal/bootstrap_node.js
|
||||
+++ node/lib/internal/bootstrap_node.js
|
||||
@@ -122,10 +122,46 @@
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = new Buffer(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (NativeModule.exists('_third_party_main')) {
|
||||
// To allow people to extend Node in different ways, this hook allows
|
||||
// one to drop a file lib/_third_party_main.js into the build
|
||||
// directory which will be executed instead of Node's normal loading.
|
||||
process.nextTick(function() {
|
||||
--- node/lib/module.js
|
||||
+++ node/lib/module.js
|
||||
@@ -28,14 +28,12 @@
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs');
|
||||
const path = require('path');
|
||||
-const {
|
||||
- internalModuleReadFile,
|
||||
- internalModuleStat
|
||||
-} = process.binding('fs');
|
||||
+const internalModuleReadFile = function (f) { return require('fs').internalModuleReadFile(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
|
||||
const experimentalModules = !!process.binding('config').experimentalModules;
|
||||
|
||||
const errors = require('internal/errors');
|
||||
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -265,10 +265,11 @@
|
||||
V(shell_string, "shell") \
|
||||
V(signal_string, "signal") \
|
||||
V(size_string, "size") \
|
||||
V(sni_context_err_string, "Invalid SNI context") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
+ V(sourceless_string, "sourceless") \
|
||||
V(speed_string, "speed") \
|
||||
V(stack_string, "stack") \
|
||||
V(status_string, "status") \
|
||||
V(stdio_string, "stdio") \
|
||||
V(stream_string, "stream") \
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -485,12 +485,10 @@
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
start_io_thread_async.data = this;
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
if (options.inspector_enabled()) {
|
||||
// This will return false if listen failed on the inspector port.
|
||||
return StartIoThread(options.wait_for_connect());
|
||||
}
|
||||
return true;
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3726,17 +3726,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -3746,14 +3739,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -57,10 +57,11 @@
|
||||
using v8::String;
|
||||
using v8::Symbol;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -573,18 +574,20 @@
|
||||
MaybeLocal<Integer> lineOffset = GetLineOffsetArg(env, options);
|
||||
MaybeLocal<Integer> columnOffset = GetColumnOffsetArg(env, options);
|
||||
Maybe<bool> maybe_display_errors = GetDisplayErrorsArg(env, options);
|
||||
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, options);
|
||||
Maybe<bool> maybe_produce_cached_data = GetProduceCachedData(env, options);
|
||||
+ Maybe<bool> maybe_sourceless = GetSourceless(env, options);
|
||||
MaybeLocal<Context> maybe_context = GetContext(env, options);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
bool display_errors = maybe_display_errors.ToChecked();
|
||||
bool produce_cached_data = maybe_produce_cached_data.ToChecked();
|
||||
+ bool sourceless = maybe_sourceless.ToChecked();
|
||||
|
||||
ScriptCompiler::CachedData* cached_data = nullptr;
|
||||
Local<Uint8Array> ui8;
|
||||
if (cached_data_buf.ToLocal(&ui8)) {
|
||||
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
|
||||
@@ -604,22 +607,37 @@
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
Context::Scope scope(maybe_context.FromMaybe(env->context()));
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
DecorateErrorStack(env, try_catch);
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(env->isolate(),
|
||||
v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
@@ -913,10 +931,26 @@
|
||||
Local<Value> value = maybe_value.ToLocalChecked();
|
||||
return Just(value->IsTrue());
|
||||
}
|
||||
|
||||
|
||||
+ static Maybe<bool> GetSourceless(Environment* env, Local<Value> options) {
|
||||
+ if (!options->IsObject()) {
|
||||
+ return Just(false);
|
||||
+ }
|
||||
+
|
||||
+ MaybeLocal<Value> maybe_value =
|
||||
+ options.As<Object>()->Get(env->context(),
|
||||
+ env->sourceless_string());
|
||||
+ if (maybe_value.IsEmpty())
|
||||
+ return Nothing<bool>();
|
||||
+
|
||||
+ Local<Value> value = maybe_value.ToLocalChecked();
|
||||
+ return Just(value->IsTrue());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static MaybeLocal<Integer> GetLineOffsetArg(Environment* env,
|
||||
Local<Value> options) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(env->isolate(), 0);
|
||||
|
||||
if (!options->IsObject()) {
|
||||
--- node/src/node_debug_options.cc
|
||||
+++ node/src/node_debug_options.cc
|
||||
@@ -59,10 +59,11 @@
|
||||
deprecated_debug_(false),
|
||||
break_first_line_(false),
|
||||
host_name_("127.0.0.1"), port_(-1) { }
|
||||
|
||||
bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
|
||||
+ return false;
|
||||
bool has_argument = false;
|
||||
std::string option_name;
|
||||
std::string argument;
|
||||
|
||||
auto pos = option.find("=");
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -119,8 +121,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -7911,10 +7911,14 @@
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
+ static void EnableCompilationForSourcelessUse();
|
||||
+ static void DisableCompilationForSourcelessUse();
|
||||
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
|
||||
+
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
/** Callback function for reporting failed access checks.*/
|
||||
V8_INLINE static V8_DEPRECATED(
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -830,10 +830,46 @@
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
+bool save_lazy;
|
||||
+bool save_predictable;
|
||||
+bool save_serialize_toplevel;
|
||||
+
|
||||
+
|
||||
+void V8::EnableCompilationForSourcelessUse() {
|
||||
+ save_lazy = i::FLAG_lazy;
|
||||
+ i::FLAG_lazy = false;
|
||||
+ save_predictable = i::FLAG_predictable;
|
||||
+ i::FLAG_predictable = true;
|
||||
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
|
||||
+ i::FLAG_serialize_toplevel = true;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ i::CpuFeatures::Reinitialize();
|
||||
+ i::CpuFeatures::Probe(false);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
|
||||
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
|
||||
+ i::Handle<i::SharedFunctionInfo> function_info(
|
||||
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
|
||||
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
|
||||
+ s->set_source(isolate->heap()->undefined_value());
|
||||
+}
|
||||
+
|
||||
+
|
||||
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
|
||||
|
||||
|
||||
RegisteredExtension::RegisteredExtension(Extension* extension)
|
||||
: extension_(extension) { }
|
||||
--- node/deps/v8/src/assembler.h
|
||||
+++ node/deps/v8/src/assembler.h
|
||||
@@ -297,10 +297,15 @@
|
||||
}
|
||||
|
||||
static void PrintTarget();
|
||||
static void PrintFeatures();
|
||||
|
||||
+ static void Reinitialize() {
|
||||
+ supported_ = 0;
|
||||
+ initialized_ = false;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class ExternalReference;
|
||||
friend class AssemblerBase;
|
||||
// Flush instruction cache.
|
||||
static void FlushICache(void* start, size_t size);
|
||||
--- node/deps/v8/src/objects.cc
|
||||
+++ node/deps/v8/src/objects.cc
|
||||
@@ -13206,10 +13206,13 @@
|
||||
|
||||
// Check if we should print {function} as a class.
|
||||
Handle<Object> class_start_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_start_position_symbol());
|
||||
if (class_start_position->IsSmi()) {
|
||||
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
|
||||
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
|
||||
+ }
|
||||
Handle<Object> class_end_position = JSReceiver::GetDataProperty(
|
||||
function, isolate->factory()->class_end_position_symbol());
|
||||
Handle<String> script_source(
|
||||
String::cast(Script::cast(shared_info->script())->source()), isolate);
|
||||
return isolate->factory()->NewSubString(
|
||||
--- node/deps/v8/src/parsing/parsing.cc
|
||||
+++ node/deps/v8/src/parsing/parsing.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
namespace parsing {
|
||||
|
||||
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
|
||||
DCHECK(info->is_toplevel());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
VMState<PARSER> state(isolate);
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
@@ -52,10 +53,11 @@
|
||||
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
|
||||
Isolate* isolate) {
|
||||
DCHECK(!info->is_toplevel());
|
||||
DCHECK(!shared_info.is_null());
|
||||
DCHECK_NULL(info->literal());
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
|
||||
// Create a character stream for the parser.
|
||||
Handle<String> source(String::cast(info->script()->source()));
|
||||
source = String::Flatten(source);
|
||||
isolate->counters()->total_parse_size()->Increment(source->length());
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -392,31 +392,46 @@
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
if (this->size_ < kHeaderSize) return INVALID_HEADER;
|
||||
uint32_t magic_number = GetMagicNumber();
|
||||
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
|
||||
+ if (magic_number != ComputeMagicNumber(isolate)) {
|
||||
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
|
||||
+ return MAGIC_NUMBER_MISMATCH;
|
||||
+ }
|
||||
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
|
||||
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
|
||||
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
|
||||
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
|
||||
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
|
||||
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
|
||||
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
|
||||
+ if (version_hash != Version::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
|
||||
+ return VERSION_MISMATCH;
|
||||
+ }
|
||||
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
|
||||
+ if (cpu_features & (~host_features)) {
|
||||
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
|
||||
return CPU_FEATURES_MISMATCH;
|
||||
}
|
||||
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
uint32_t max_payload_length =
|
||||
this->size_ -
|
||||
POINTER_SIZE_ALIGN(kHeaderSize +
|
||||
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
|
||||
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
|
||||
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
|
||||
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (payload_length > max_payload_length) {
|
||||
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
|
||||
+ return LENGTH_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -104,11 +104,11 @@
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
options.shell = false;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/internal/bootstrap_node.js
|
||||
+++ node/lib/internal/bootstrap_node.js
|
||||
@@ -122,10 +122,46 @@
|
||||
// There are various modes that Node can run in. The most common two
|
||||
// are running from a script and running the REPL - but there are a few
|
||||
// others like the debugger or running --eval arguments. Here we decide
|
||||
// which mode we run in.
|
||||
|
||||
+ (function () {
|
||||
+ var fs = NativeModule.require('fs');
|
||||
+ var vm = NativeModule.require('vm');
|
||||
+ function readPrelude (fd) {
|
||||
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
|
||||
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
|
||||
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
|
||||
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
|
||||
+ if (!PRELUDE_POSITION) {
|
||||
+ // no prelude - remove entrypoint from argv[1]
|
||||
+ process.argv.splice(1, 1);
|
||||
+ return { undoPatch: true };
|
||||
+ }
|
||||
+ var prelude = new Buffer(PRELUDE_SIZE);
|
||||
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
|
||||
+ if (read !== PRELUDE_SIZE) {
|
||||
+ console.error('Pkg: Error reading from file.');
|
||||
+ process.exit(1);
|
||||
+ }
|
||||
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
|
||||
+ var fn = s.runInThisContext();
|
||||
+ return fn(process, NativeModule.require,
|
||||
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
|
||||
+ }
|
||||
+ (function () {
|
||||
+ var fd = fs.openSync(process.execPath, 'r');
|
||||
+ var result = readPrelude(fd);
|
||||
+ if (result && result.undoPatch) {
|
||||
+ var bindingFs = process.binding('fs');
|
||||
+ fs.internalModuleStat = bindingFs.internalModuleStat;
|
||||
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
|
||||
+ fs.closeSync(fd);
|
||||
+ }
|
||||
+ }());
|
||||
+ }());
|
||||
+
|
||||
if (NativeModule.exists('_third_party_main')) {
|
||||
// To allow people to extend Node in different ways, this hook allows
|
||||
// one to drop a file lib/_third_party_main.js into the build
|
||||
// directory which will be executed instead of Node's normal loading.
|
||||
process.nextTick(function() {
|
||||
--- node/lib/module.js
|
||||
+++ node/lib/module.js
|
||||
@@ -28,14 +28,12 @@
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const internalFS = require('internal/fs');
|
||||
const path = require('path');
|
||||
-const {
|
||||
- internalModuleReadFile,
|
||||
- internalModuleStat
|
||||
-} = process.binding('fs');
|
||||
+const internalModuleReadFile = function (f) { return require('fs').internalModuleReadFile(f); };
|
||||
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
|
||||
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
|
||||
const experimentalModules = !!process.binding('config').experimentalModules;
|
||||
|
||||
const errors = require('internal/errors');
|
||||
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -266,10 +266,11 @@
|
||||
V(shell_string, "shell") \
|
||||
V(signal_string, "signal") \
|
||||
V(size_string, "size") \
|
||||
V(sni_context_err_string, "Invalid SNI context") \
|
||||
V(sni_context_string, "sni_context") \
|
||||
+ V(sourceless_string, "sourceless") \
|
||||
V(speed_string, "speed") \
|
||||
V(stack_string, "stack") \
|
||||
V(status_string, "status") \
|
||||
V(stdio_string, "stdio") \
|
||||
V(stream_string, "stream") \
|
||||
--- node/src/inspector_agent.cc
|
||||
+++ node/src/inspector_agent.cc
|
||||
@@ -485,12 +485,10 @@
|
||||
&start_io_thread_async,
|
||||
StartIoThreadAsyncCallback));
|
||||
start_io_thread_async.data = this;
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
if (options.inspector_enabled()) {
|
||||
// This will return false if listen failed on the inspector port.
|
||||
return StartIoThread(options.wait_for_connect());
|
||||
}
|
||||
return true;
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3726,17 +3726,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
-#if HAVE_INSPECTOR
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
// Make sure file descriptors 0-2 are valid before we start logging anything.
|
||||
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
|
||||
struct stat ignored;
|
||||
if (fstat(fd, &ignored) == 0)
|
||||
continue;
|
||||
@@ -3746,14 +3739,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
-#if HAVE_INSPECTOR
|
||||
- CHECK_EQ(err, 0);
|
||||
-#endif // HAVE_INSPECTOR
|
||||
-
|
||||
#ifndef NODE_SHARED_MODE
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -57,10 +57,11 @@
|
||||
using v8::String;
|
||||
using v8::Symbol;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -573,18 +574,20 @@
|
||||
MaybeLocal<Integer> lineOffset = GetLineOffsetArg(env, options);
|
||||
MaybeLocal<Integer> columnOffset = GetColumnOffsetArg(env, options);
|
||||
Maybe<bool> maybe_display_errors = GetDisplayErrorsArg(env, options);
|
||||
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, options);
|
||||
Maybe<bool> maybe_produce_cached_data = GetProduceCachedData(env, options);
|
||||
+ Maybe<bool> maybe_sourceless = GetSourceless(env, options);
|
||||
MaybeLocal<Context> maybe_context = GetContext(env, options);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
bool display_errors = maybe_display_errors.ToChecked();
|
||||
bool produce_cached_data = maybe_produce_cached_data.ToChecked();
|
||||
+ bool sourceless = maybe_sourceless.ToChecked();
|
||||
|
||||
ScriptCompiler::CachedData* cached_data = nullptr;
|
||||
Local<Uint8Array> ui8;
|
||||
if (cached_data_buf.ToLocal(&ui8)) {
|
||||
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
|
||||
@@ -604,22 +607,37 @@
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
Context::Scope scope(maybe_context.FromMaybe(env->context()));
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::EnableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ V8::DisableCompilationForSourcelessUse();
|
||||
+ }
|
||||
+
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
DecorateErrorStack(env, try_catch);
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ if (!source.GetCachedData()->rejected) {
|
||||
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
contextify_script->script_.Reset(env->isolate(),
|
||||
v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
@@ -913,10 +931,26 @@
|
||||
Local<Value> value = maybe_value.ToLocalChecked();
|
||||
return Just(value->IsTrue());
|
||||
}
|
||||
|
||||
|
||||
+ static Maybe<bool> GetSourceless(Environment* env, Local<Value> options) {
|
||||
+ if (!options->IsObject()) {
|
||||
+ return Just(false);
|
||||
+ }
|
||||
+
|
||||
+ MaybeLocal<Value> maybe_value =
|
||||
+ options.As<Object>()->Get(env->context(),
|
||||
+ env->sourceless_string());
|
||||
+ if (maybe_value.IsEmpty())
|
||||
+ return Nothing<bool>();
|
||||
+
|
||||
+ Local<Value> value = maybe_value.ToLocalChecked();
|
||||
+ return Just(value->IsTrue());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static MaybeLocal<Integer> GetLineOffsetArg(Environment* env,
|
||||
Local<Value> options) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(env->isolate(), 0);
|
||||
|
||||
if (!options->IsObject()) {
|
||||
--- node/src/node_debug_options.cc
|
||||
+++ node/src/node_debug_options.cc
|
||||
@@ -59,10 +59,11 @@
|
||||
deprecated_debug_(false),
|
||||
break_first_line_(false),
|
||||
host_name_("127.0.0.1"), port_(-1) { }
|
||||
|
||||
bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
|
||||
+ return false;
|
||||
bool has_argument = false;
|
||||
std::string option_name;
|
||||
std::string argument;
|
||||
|
||||
auto pos = option.find("=");
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -20,10 +20,12 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+int reorder(int argc, char** argv);
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
@@ -67,11 +69,11 @@
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = nullptr;
|
||||
// Now that conversion is done, we can finally start.
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#else
|
||||
// UNIX
|
||||
#ifdef __linux__
|
||||
#include <elf.h>
|
||||
@@ -119,8 +121,75 @@
|
||||
#endif
|
||||
// Disable stdio buffering, it interacts poorly with printf()
|
||||
// calls elsewhere in the program (e.g., any logging from V8.)
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+int strlen2 (char* s) {
|
||||
+ int len = 0;
|
||||
+ while (*s) {
|
||||
+ len += 1;
|
||||
+ s += 1;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+bool should_set_dummy() {
|
||||
+#ifdef _WIN32
|
||||
+ #define MAX_ENV_LENGTH 32767
|
||||
+ char execpath_env[MAX_ENV_LENGTH];
|
||||
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
|
||||
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#else
|
||||
+ const char* execpath_env = getenv("PKG_EXECPATH");
|
||||
+ if (!execpath_env) return true;
|
||||
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+// for uv_setup_args
|
||||
+int adjacent(int argc, char** argv) {
|
||||
+ size_t size = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ size += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ char* args = new char[size];
|
||||
+ size_t pos = 0;
|
||||
+ for (int i = 0; i < argc; i++) {
|
||||
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
|
||||
+ argv[i] = &args[pos];
|
||||
+ pos += strlen(argv[i]) + 1;
|
||||
+ }
|
||||
+ return node::Start(argc, argv);
|
||||
+}
|
||||
+
|
||||
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
|
||||
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ char* bakery = (char*) BAKERY;
|
||||
+ while (true) {
|
||||
+ size_t width = strlen2(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ if (should_set_dummy()) {
|
||||
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"v12.13.1": [
|
||||
"node.v12.13.1.cpp.patch"
|
||||
],
|
||||
"v12.2.0": [
|
||||
"node.v12.2.0.cpp.patch"
|
||||
],
|
||||
"v10.17.0": [
|
||||
"node.v10.17.0.cpp.patch"
|
||||
],
|
||||
"v10.15.3": [
|
||||
"node.v10.15.3.cpp.patch"
|
||||
],
|
||||
"v8.16.2": [
|
||||
"node.v8.16.2.cpp.patch"
|
||||
],
|
||||
"v8.16.0": [
|
||||
"node.v8.16.0.cpp.patch"
|
||||
],
|
||||
"v6.17.1": [
|
||||
"node.v6.17.1.cpp.patch"
|
||||
],
|
||||
"v4.9.1": [
|
||||
"backport.R32768.patch",
|
||||
"backport.PR4777.for.N4.patch",
|
||||
"backport.PR5159.for.N4.patch",
|
||||
"backport.PR5343.for.N4.patch",
|
||||
"node.v4.9.1.cpp.patch"
|
||||
],
|
||||
"v0.12.18": [
|
||||
"backport.R00000.patch",
|
||||
"backport.R24002.patch",
|
||||
"backport.R24204.patch",
|
||||
"backport.R24262.patch",
|
||||
"backport.R24266.patch",
|
||||
"backport.R24523.patch",
|
||||
"backport.R24543.patch",
|
||||
"backport.R24639.patch",
|
||||
"backport.R24642.patch",
|
||||
"backport.R24643.patch",
|
||||
"backport.R24644.patch",
|
||||
"backport.R24824.patch",
|
||||
"backport.R25039.patch",
|
||||
"backport.R25444.patch",
|
||||
"backport.PR4777.for.N0.patch",
|
||||
"backport.PR5343.for.N0.patch",
|
||||
"node.v0.12.18.cpp.patch"
|
||||
]
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"localPlace": "{tag}/{from}-{nodeVersion}-{platform}-{arch}",
|
||||
"remotePlace": "uploaded-{tag}-node-{nodeVersion}-{platform}-{arch}"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# pkg-fetch
|
||||
|
||||
Github Releases page of this project contains base binaries,
|
||||
used by `pkg` to create executables. `pkg-fetch` npm package
|
||||
downloads base binaries or compiles them from source.
|
||||
Reference in New Issue
Block a user