|
127 | 127 | const config = getBinding('config');
|
128 | 128 |
|
129 | 129 | const codeCache = getInternalBinding('code_cache');
|
| 130 | + const codeCacheHash = getInternalBinding('code_cache_hash'); |
| 131 | + const sourceHash = getInternalBinding('natives_hash'); |
130 | 132 | const compiledWithoutCache = NativeModule.compiledWithoutCache = [];
|
131 | 133 | const compiledWithCache = NativeModule.compiledWithCache = [];
|
132 | 134 |
|
|
232 | 234 | };
|
233 | 235 |
|
234 | 236 | NativeModule.prototype.compile = function() {
|
235 |
| - let source = NativeModule.getSource(this.id); |
| 237 | + const id = this.id; |
| 238 | + let source = NativeModule.getSource(id); |
236 | 239 | source = NativeModule.wrap(source);
|
237 | 240 |
|
238 | 241 | this.loading = true;
|
239 | 242 |
|
240 | 243 | try {
|
| 244 | + // Currently V8 only checks that the length of the source code is the |
| 245 | + // same as the code used to generate the hash, so we add an additional |
| 246 | + // check here: |
| 247 | + // 1. During compile time, when generating node_javascript.cc and |
| 248 | + // node_code_cache.cc, we compute and include the hash of the |
| 249 | + // (unwrapped) JavaScript source in both. |
| 250 | + // 2. At runtime, we check that the hash of the code being compiled |
| 251 | + // and the hash of the code used to generate the cache |
| 252 | + // (inside the wrapper) is the same. |
| 253 | + // This is based on the assumptions: |
| 254 | + // 1. `internalBinding('code_cache_hash')` must be in sync with |
| 255 | + // `internalBinding('code_cache')` (same C++ file) |
| 256 | + // 2. `internalBinding('natives_hash')` must be in sync with |
| 257 | + // `process.binding('natives')` (same C++ file) |
| 258 | + // 3. If `internalBinding('natives_hash')` is in sync with |
| 259 | + // `internalBinding('natives_hash')`, then the (unwrapped) |
| 260 | + // code used to generate `internalBinding('code_cache')` |
| 261 | + // should be in sync with the (unwrapped) code in |
| 262 | + // `process.binding('natives')` |
| 263 | + // There will be, however, false positives if the wrapper used |
| 264 | + // to generate the cache is different from the one used at run time, |
| 265 | + // and the length of the wrapper somehow stays the same. |
| 266 | + // But that should be rare and can be eased once we make the |
| 267 | + // two bootstrappers cached and checked as well. |
| 268 | + const cache = codeCacheHash[id] && |
| 269 | + (codeCacheHash[id] === sourceHash[id]) ? codeCache[id] : undefined; |
| 270 | + |
241 | 271 | // (code, filename, lineOffset, columnOffset
|
242 | 272 | // cachedData, produceCachedData, parsingContext)
|
243 | 273 | const script = new ContextifyScript(
|
244 | 274 | source, this.filename, 0, 0,
|
245 |
| - codeCache[this.id], false, undefined |
| 275 | + cache, false, undefined |
246 | 276 | );
|
247 | 277 |
|
| 278 | + // This will be used to create code cache in tools/generate_code_cache.js |
248 | 279 | this.script = script;
|
249 | 280 |
|
250 | 281 | // One of these conditions may be false when any of the inputs
|
251 | 282 | // of the `node_js2c` target in node.gyp is modified.
|
252 |
| - // FIXME(joyeecheung): |
253 |
| - // 1. Figure out how to resolve the dependency issue. When the |
254 |
| - // code cache was introduced we were at a point where refactoring |
255 |
| - // node.gyp may not be worth the effort. |
256 |
| - // 2. Calculate checksums in both js2c and generate_code_cache.js |
257 |
| - // and compare them before compiling the native modules since |
258 |
| - // V8 only checks the length of the source to decide whether to |
259 |
| - // reject the cache. |
260 |
| - if (!codeCache[this.id] || script.cachedDataRejected) { |
| 283 | + // FIXME(joyeecheung): Figure out how to resolve the dependency issue. |
| 284 | + // When the code cache was introduced we were at a point where refactoring |
| 285 | + // node.gyp may not be worth the effort. |
| 286 | + if (!cache || script.cachedDataRejected) { |
261 | 287 | compiledWithoutCache.push(this.id);
|
262 | 288 | } else {
|
263 | 289 | compiledWithCache.push(this.id);
|
|
0 commit comments