| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent fd913fe commit ee461fe
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,9 @@ | |||
| 6 | 6 | // cannot be tampered with even with --expose-internals. | |
| 7 | 7 | ||
| 8 | 8 | const { NativeModule } = require('internal/bootstrap/loaders'); | |
| 9 | - const { source, compileCodeCache } = internalBinding('native_module'); | ||
| 9 | + const { | ||
| 10 | + source, getCodeCache, compileFunction | ||
| 11 | + } = internalBinding('native_module'); | ||
| 10 | 12 | const { hasTracing } = process.binding('config'); | |
| 11 | 13 | ||
| 12 | 14 | const depsModule = Object.keys(source).filter( | |
@@ -70,6 +72,7 @@ module.exports = { | |||
| 70 | 72 | (key) => !cannotUseCache.includes(key) | |
| 71 | 73 | ), | |
| 72 | 74 | getSource(id) { return source[id]; }, | |
| 73 | - getCodeCache: compileCodeCache, | ||
| 75 | + getCodeCache, | ||
| 76 | + compileFunction, | ||
| 74 | 77 | cannotUseCache | |
| 75 | 78 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -110,7 +110,6 @@ typedef int mode_t; | |||
| 110 | 110 | ||
| 111 | 111 | namespace node { | |
| 112 | 112 | ||
| 113 | - using native_module::NativeModuleLoader; | ||
| 114 | 113 | using options_parser::kAllowedInEnvironment; | |
| 115 | 114 | using options_parser::kDisallowedInEnvironment; | |
| 116 | 115 | using v8::Array; | |
@@ -162,7 +161,6 @@ double prog_start_time; | |||
| 162 | 161 | Mutex per_process_opts_mutex; | |
| 163 | 162 | std::shared_ptr<PerProcessOptions> per_process_opts { | |
| 164 | 163 | new PerProcessOptions() }; | |
| 165 | - NativeModuleLoader per_process_loader; | ||
| 166 | 164 | static Mutex node_isolate_mutex; | |
| 167 | 165 | static Isolate* node_isolate; | |
| 168 | 166 | ||
@@ -1191,7 +1189,7 @@ static MaybeLocal<Value> ExecuteBootstrapper( | |||
| 1191 | 1189 | const char* id, | |
| 1192 | 1190 | std::vector<Local<String>>* parameters, | |
| 1193 | 1191 | std::vector<Local<Value>>* arguments) { | |
| 1194 | - MaybeLocal<Value> ret = per_process_loader.CompileAndCall( | ||
| 1192 | + MaybeLocal<Value> ret = per_process::native_module_loader.CompileAndCall( | ||
| 1195 | 1193 | env->context(), id, parameters, arguments, env); | |
| 1196 | 1194 | ||
| 1197 | 1195 | // If there was an error during bootstrap then it was either handled by the | |
@@ -1908,7 +1906,7 @@ Local<Context> NewContext(Isolate* isolate, | |||
| 1908 | 1906 | std::vector<Local<String>> parameters = { | |
| 1909 | 1907 | FIXED_ONE_BYTE_STRING(isolate, "global")}; | |
| 1910 | 1908 | std::vector<Local<Value>> arguments = {context->Global()}; | |
| 1911 | - MaybeLocal<Value> result = per_process_loader.CompileAndCall( | ||
| 1909 | + MaybeLocal<Value> result = per_process::native_module_loader.CompileAndCall( | ||
| 1912 | 1910 | context, "internal/per_context", ¶meters, &arguments, nullptr); | |
| 1913 | 1911 | if (result.IsEmpty()) { | |
| 1914 | 1912 | // Execution failed during context creation. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -389,13 +389,14 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) { | |||
| 389 | 389 | exports->SetPrototype(env->context(), Null(env->isolate())).FromJust()); | |
| 390 | 390 | DefineConstants(env->isolate(), exports); | |
| 391 | 391 | } else if (!strcmp(*module_v, "natives")) { | |
| 392 | - exports = per_process_loader.GetSourceObject(env->context()); | ||
| 392 | + exports = per_process::native_module_loader.GetSourceObject(env->context()); | ||
| 393 | 393 | // Legacy feature: process.binding('natives').config contains stringified | |
| 394 | 394 | // config.gypi | |
| 395 | 395 | CHECK(exports | |
| 396 | 396 | ->Set(env->context(), | |
| 397 | 397 | env->config_string(), | |
| 398 | - per_process_loader.GetConfigString(env->isolate())) | ||
| 398 | + per_process::native_module_loader.GetConfigString( | ||
| 399 | + env->isolate())) | ||
| 399 | 400 | .FromJust()); | |
| 400 | 401 | } else { | |
| 401 | 402 | return ThrowIfNoSuchModule(env, *module_v); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -91,7 +91,6 @@ extern bool v8_initialized; | |||
| 91 | 91 | ||
| 92 | 92 | extern Mutex per_process_opts_mutex; | |
| 93 | 93 | extern std::shared_ptr<PerProcessOptions> per_process_opts; | |
| 94 | - extern native_module::NativeModuleLoader per_process_loader; | ||
| 95 | 94 | ||
| 96 | 95 | // Forward declaration | |
| 97 | 96 | class Environment; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,6 +3,11 @@ | |||
| 3 | 3 | #include "node_internals.h" | |
| 4 | 4 | ||
| 5 | 5 | namespace node { | |
| 6 | + | ||
| 7 | + namespace per_process { | ||
| 8 | + native_module::NativeModuleLoader native_module_loader; | ||
| 9 | + } // namespace per_process | ||
| 10 | + | ||
| 6 | 11 | namespace native_module { | |
| 7 | 12 | ||
| 8 | 13 | using v8::Array; | |
@@ -78,13 +83,14 @@ void NativeModuleLoader::GetCacheUsage( | |||
| 78 | 83 | void NativeModuleLoader::SourceObjectGetter( | |
| 79 | 84 | Local<Name> property, const PropertyCallbackInfo<Value>& info) { | |
| 80 | 85 | Local<Context> context = info.GetIsolate()->GetCurrentContext(); | |
| 81 | - info.GetReturnValue().Set(per_process_loader.GetSourceObject(context)); | ||
| 86 | + info.GetReturnValue().Set( | ||
| 87 | + per_process::native_module_loader.GetSourceObject(context)); | ||
| 82 | 88 | } | |
| 83 | 89 | ||
| 84 | 90 | void NativeModuleLoader::ConfigStringGetter( | |
| 85 | 91 | Local<Name> property, const PropertyCallbackInfo<Value>& info) { | |
| 86 | 92 | info.GetReturnValue().Set( | |
| 87 | - per_process_loader.GetConfigString(info.GetIsolate())); | ||
| 93 | + per_process::native_module_loader.GetConfigString(info.GetIsolate())); | ||
| 88 | 94 | } | |
| 89 | 95 | ||
| 90 | 96 | Local<Object> NativeModuleLoader::GetSourceObject( | |
@@ -96,41 +102,62 @@ Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) const { | |||
| 96 | 102 | return config_.ToStringChecked(isolate); | |
| 97 | 103 | } | |
| 98 | 104 | ||
| 99 | - Local<String> NativeModuleLoader::GetSource(Isolate* isolate, | ||
| 100 | - const char* id) const { | ||
| 101 | - const auto it = source_.find(id); | ||
| 102 | - CHECK_NE(it, source_.end()); | ||
| 103 | - return it->second.ToStringChecked(isolate); | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | 105 | NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) { | |
| 107 | 106 | LoadJavaScriptSource(); | |
| 108 | 107 | LoadCodeCache(); | |
| 109 | 108 | } | |
| 110 | 109 | ||
| 111 | - void NativeModuleLoader::CompileCodeCache( | ||
| 112 | - const FunctionCallbackInfo<Value>& args) { | ||
| 110 | + // This is supposed to be run only by the main thread in | ||
| 111 | + // tools/generate_code_cache.js | ||
| 112 | + void NativeModuleLoader::GetCodeCache(const FunctionCallbackInfo<Value>& args) { | ||
| 113 | 113 | Environment* env = Environment::GetCurrent(args); | |
| 114 | + Isolate* isolate = env->isolate(); | ||
| 115 | + CHECK(env->is_main_thread()); | ||
| 116 | + | ||
| 114 | 117 | CHECK(args[0]->IsString()); | |
| 115 | - node::Utf8Value id(env->isolate(), args[0].As<String>()); | ||
| 118 | + node::Utf8Value id_v(isolate, args[0].As<String>()); | ||
| 119 | + const char* id = *id_v; | ||
| 116 | 120 | ||
| 117 | - // TODO(joyeecheung): allow compiling cache for bootstrapper by | ||
| 118 | - // switching on id | ||
| 119 | - MaybeLocal<Value> result = | ||
| 120 | - CompileAsModule(env, *id, CompilationResultType::kCodeCache); | ||
| 121 | - if (!result.IsEmpty()) { | ||
| 122 | - args.GetReturnValue().Set(result.ToLocalChecked()); | ||
| 121 | + const NativeModuleLoader& loader = per_process::native_module_loader; | ||
| 122 | + MaybeLocal<Uint8Array> ret = loader.GetCodeCache(isolate, id); | ||
| 123 | + if (!ret.IsEmpty()) { | ||
| 124 | + args.GetReturnValue().Set(ret.ToLocalChecked()); | ||
| 123 | 125 | } | |
| 124 | 126 | } | |
| 125 | 127 | ||
| 128 | + // This is supposed to be run only by the main thread in | ||
| 129 | + // tools/generate_code_cache.js | ||
| 130 | + MaybeLocal<Uint8Array> NativeModuleLoader::GetCodeCache(Isolate* isolate, | ||
| 131 | + const char* id) const { | ||
| 132 | + EscapableHandleScope scope(isolate); | ||
| 133 | + Mutex::ScopedLock lock(code_cache_mutex_); | ||
| 134 | + | ||
| 135 | + ScriptCompiler::CachedData* cached_data = nullptr; | ||
| 136 | + const auto it = code_cache_.find(id); | ||
| 137 | + if (it == code_cache_.end()) { | ||
| 138 | + // The module has not been compiled before. | ||
| 139 | + return MaybeLocal<Uint8Array>(); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + cached_data = it->second.get(); | ||
| 143 | + | ||
| 144 | + MallocedBuffer<uint8_t> copied(cached_data->length); | ||
| 145 | + memcpy(copied.data, cached_data->data, cached_data->length); | ||
| 146 | + Local<ArrayBuffer> buf = | ||
| 147 | + ArrayBuffer::New(isolate, | ||
| 148 | + copied.release(), | ||
| 149 | + cached_data->length, | ||
| 150 | + ArrayBufferCreationMode::kInternalized); | ||
| 151 | + return scope.Escape(Uint8Array::New(buf, 0, cached_data->length)); | ||
| 152 | + } | ||
| 153 | + | ||
| 126 | 154 | void NativeModuleLoader::CompileFunction( | |
| 127 | 155 | const FunctionCallbackInfo<Value>& args) { | |
| 128 | 156 | Environment* env = Environment::GetCurrent(args); | |
| 129 | 157 | CHECK(args[0]->IsString()); | |
| 130 | 158 | node::Utf8Value id(env->isolate(), args[0].As<String>()); | |
| 131 | 159 | ||
| 132 | - MaybeLocal<Value> result = | ||
| 133 | - CompileAsModule(env, *id, CompilationResultType::kFunction); | ||
| 160 | + MaybeLocal<Function> result = CompileAsModule(env, *id); | ||
| 134 | 161 | if (!result.IsEmpty()) { | |
| 135 | 162 | args.GetReturnValue().Set(result.ToLocalChecked()); | |
| 136 | 163 | } | |
@@ -145,57 +172,43 @@ MaybeLocal<Value> NativeModuleLoader::CompileAndCall( | |||
| 145 | 172 | std::vector<Local<Value>>* arguments, | |
| 146 | 173 | Environment* optional_env) { | |
| 147 | 174 | Isolate* isolate = context->GetIsolate(); | |
| 148 | - MaybeLocal<Value> compiled = per_process_loader.LookupAndCompile( | ||
| 149 | - context, id, parameters, CompilationResultType::kFunction, nullptr); | ||
| 175 | + MaybeLocal<Function> compiled = | ||
| 176 | + per_process::native_module_loader.LookupAndCompile( | ||
| 177 | + context, id, parameters, nullptr); | ||
| 150 | 178 | if (compiled.IsEmpty()) { | |
| 151 | - return compiled; | ||
| 179 | + return MaybeLocal<Value>(); | ||
| 152 | 180 | } | |
| 153 | 181 | Local<Function> fn = compiled.ToLocalChecked().As<Function>(); | |
| 154 | 182 | return fn->Call( | |
| 155 | 183 | context, v8::Null(isolate), arguments->size(), arguments->data()); | |
| 156 | 184 | } | |
| 157 | 185 | ||
| 158 | - MaybeLocal<Value> NativeModuleLoader::CompileAsModule( | ||
| 159 | - Environment* env, const char* id, CompilationResultType result) { | ||
| 186 | + MaybeLocal<Function> NativeModuleLoader::CompileAsModule(Environment* env, | ||
| 187 | + const char* id) { | ||
| 160 | 188 | std::vector<Local<String>> parameters = {env->exports_string(), | |
| 161 | 189 | env->require_string(), | |
| 162 | 190 | env->module_string(), | |
| 163 | 191 | env->process_string(), | |
| 164 | 192 | env->internal_binding_string()}; | |
| 165 | - return per_process_loader.LookupAndCompile( | ||
| 166 | - env->context(), id, ¶meters, result, env); | ||
| 167 | - } | ||
| 168 | - | ||
| 169 | - // Returns nullptr if there is no code cache corresponding to the id | ||
| 170 | - ScriptCompiler::CachedData* NativeModuleLoader::GetCachedData( | ||
| 171 | - const char* id) const { | ||
| 172 | - const auto it = per_process_loader.code_cache_.find(id); | ||
| 173 | - // This could be false if the module cannot be cached somehow. | ||
| 174 | - // See lib/internal/bootstrap/cache.js on the modules that cannot be cached | ||
| 175 | - if (it == per_process_loader.code_cache_.end()) { | ||
| 176 | - return nullptr; | ||
| 177 | - } | ||
| 178 | - | ||
| 179 | - const uint8_t* code_cache_value = it->second.one_bytes_data(); | ||
| 180 | - size_t code_cache_length = it->second.length(); | ||
| 181 | - | ||
| 182 | - return new ScriptCompiler::CachedData(code_cache_value, code_cache_length); | ||
| 193 | + return per_process::native_module_loader.LookupAndCompile( | ||
| 194 | + env->context(), id, ¶meters, env); | ||
| 183 | 195 | } | |
| 184 | 196 | ||
| 185 | 197 | // Returns Local<Function> of the compiled module if return_code_cache | |
| 186 | 198 | // is false (we are only compiling the function). | |
| 187 | 199 | // Otherwise return a Local<Object> containing the cache. | |
| 188 | - MaybeLocal<Value> NativeModuleLoader::LookupAndCompile( | ||
| 200 | + MaybeLocal<Function> NativeModuleLoader::LookupAndCompile( | ||
| 189 | 201 | Local<Context> context, | |
| 190 | 202 | const char* id, | |
| 191 | 203 | std::vector<Local<String>>* parameters, | |
| 192 | - CompilationResultType result_type, | ||
| 193 | 204 | Environment* optional_env) { | |
| 194 | 205 | Isolate* isolate = context->GetIsolate(); | |
| 195 | 206 | EscapableHandleScope scope(isolate); | |
| 196 | 207 | Local<Value> ret; // Used to convert to MaybeLocal before return | |
| 197 | 208 | ||
| 198 | - Local<String> source = GetSource(isolate, id); | ||
| 209 | + const auto source_it = source_.find(id); | ||
| 210 | + CHECK_NE(source_it, source_.end()); | ||
| 211 | + Local<String> source = source_it->second.ToStringChecked(isolate); | ||
| 199 | 212 | ||
| 200 | 213 | std::string filename_s = id + std::string(".js"); | |
| 201 | 214 | Local<String> filename = | |
@@ -204,31 +217,24 @@ MaybeLocal<Value> NativeModuleLoader::LookupAndCompile( | |||
| 204 | 217 | Local<Integer> column_offset = Integer::New(isolate, 0); | |
| 205 | 218 | ScriptOrigin origin(filename, line_offset, column_offset); | |
| 206 | 219 | ||
| 207 | - bool use_cache = false; | ||
| 208 | - ScriptCompiler::CachedData* cached_data = nullptr; | ||
| 220 | + Mutex::ScopedLock lock(code_cache_mutex_); | ||
| 209 | 221 | ||
| 210 | - // 1. We won't even check the existence of the cache if the binary is not | ||
| 211 | - // built with them. | ||
| 212 | - // 2. If we are generating code cache for tools/general_code_cache.js, we | ||
| 213 | - // are not going to use any cache ourselves. | ||
| 214 | - if (has_code_cache_ && result_type == CompilationResultType::kFunction) { | ||
| 215 | - cached_data = GetCachedData(id); | ||
| 216 | - if (cached_data != nullptr) { | ||
| 217 | - use_cache = true; | ||
| 222 | + ScriptCompiler::CachedData* cached_data = nullptr; | ||
| 223 | + { | ||
| 224 | + auto cache_it = code_cache_.find(id); | ||
| 225 | + if (cache_it != code_cache_.end()) { | ||
| 226 | + // Transfer ownership to ScriptCompiler::Source later. | ||
| 227 | + cached_data = cache_it->second.release(); | ||
| 228 | + code_cache_.erase(cache_it); | ||
| 218 | 229 | } | |
| 219 | 230 | } | |
| 220 | 231 | ||
| 232 | + const bool use_cache = cached_data != nullptr; | ||
| 233 | + ScriptCompiler::CompileOptions options = | ||
| 234 | + use_cache ? ScriptCompiler::kConsumeCodeCache | ||
| 235 | + : ScriptCompiler::kEagerCompile; | ||
| 221 | 236 | ScriptCompiler::Source script_source(source, origin, cached_data); | |
| 222 | 237 | ||
| 223 | - ScriptCompiler::CompileOptions options; | ||
| 224 | - if (result_type == CompilationResultType::kCodeCache) { | ||
| 225 | - options = ScriptCompiler::kEagerCompile; | ||
| 226 | - } else if (use_cache) { | ||
| 227 | - options = ScriptCompiler::kConsumeCodeCache; | ||
| 228 | - } else { | ||
| 229 | - options = ScriptCompiler::kNoCompileOptions; | ||
| 230 | - } | ||
| 231 | - | ||
| 232 | 238 | MaybeLocal<Function> maybe_fun = | |
| 233 | 239 | ScriptCompiler::CompileFunctionInContext(context, | |
| 234 | 240 | &script_source, | |
@@ -244,10 +250,14 @@ MaybeLocal<Value> NativeModuleLoader::LookupAndCompile( | |||
| 244 | 250 | // In the case of early errors, v8 is already capable of | |
| 245 | 251 | // decorating the stack for us - note that we use CompileFunctionInContext | |
| 246 | 252 | // so there is no need to worry about wrappers. | |
| 247 | - return MaybeLocal<Value>(); | ||
| 253 | + return MaybeLocal<Function>(); | ||
| 248 | 254 | } | |
| 249 | 255 | ||
| 250 | 256 | Local<Function> fun = maybe_fun.ToLocalChecked(); | |
| 257 | + // XXX(joyeecheung): this bookkeeping is not exactly accurate because | ||
| 258 | + // it only starts after the Environment is created, so the per_context.js | ||
| 259 | + // will never be in any of these two sets, but the two sets are only for | ||
| 260 | + // testing anyway. | ||
| 251 | 261 | if (use_cache) { | |
| 252 | 262 | if (optional_env != nullptr) { | |
| 253 | 263 | // This could happen when Node is run with any v8 flag, but | |
@@ -264,29 +274,15 @@ MaybeLocal<Value> NativeModuleLoader::LookupAndCompile( | |||
| 264 | 274 | } | |
| 265 | 275 | } | |
| 266 | 276 | ||
| 267 | - if (result_type == CompilationResultType::kCodeCache) { | ||
| 268 | - std::unique_ptr<ScriptCompiler::CachedData> cached_data( | ||
| 269 | - ScriptCompiler::CreateCodeCacheForFunction(fun)); | ||
| 270 | - CHECK_NE(cached_data, nullptr); | ||
| 271 | - size_t cached_data_length = cached_data->length; | ||
| 272 | - // Since we have no special allocator to create an ArrayBuffer | ||
| 273 | - // from a new'ed pointer, we will need to copy it - but this | ||
| 274 | - // code path is only run by the tooling that generates the code | ||
| 275 | - // cache to be bundled in the binary | ||
| 276 | - // so it should be fine. | ||
| 277 | - MallocedBuffer<uint8_t> copied(cached_data->length); | ||
| 278 | - memcpy(copied.data, cached_data->data, cached_data_length); | ||
| 279 | - Local<ArrayBuffer> buf = | ||
| 280 | - ArrayBuffer::New(isolate, | ||
| 281 | - copied.release(), | ||
| 282 | - cached_data_length, | ||
| 283 | - ArrayBufferCreationMode::kInternalized); | ||
| 284 | - ret = Uint8Array::New(buf, 0, cached_data_length); | ||
| 285 | - } else { | ||
| 286 | - ret = fun; | ||
| 287 | - } | ||
| 277 | + // Generate new cache for next compilation | ||
| 278 | + std::unique_ptr<ScriptCompiler::CachedData> new_cached_data( | ||
| 279 | + ScriptCompiler::CreateCodeCacheForFunction(fun)); | ||
| 280 | + CHECK_NE(new_cached_data, nullptr); | ||
| 288 | 281 | ||
| 289 | - return scope.Escape(ret); | ||
| 282 | + // The old entry should've been erased by now so we can just emplace | ||
| 283 | + code_cache_.emplace(id, std::move(new_cached_data)); | ||
| 284 | + | ||
| 285 | + return scope.Escape(fun); | ||
| 290 | 286 | } | |
| 291 | 287 | ||
| 292 | 288 | void NativeModuleLoader::Initialize(Local<Object> target, | |
@@ -320,8 +316,7 @@ void NativeModuleLoader::Initialize(Local<Object> target, | |||
| 320 | 316 | target, "getCacheUsage", NativeModuleLoader::GetCacheUsage); | |
| 321 | 317 | env->SetMethod( | |
| 322 | 318 | target, "compileFunction", NativeModuleLoader::CompileFunction); | |
| 323 | - env->SetMethod( | ||
| 324 | - target, "compileCodeCache", NativeModuleLoader::CompileCodeCache); | ||
| 319 | + env->SetMethod(target, "getCodeCache", NativeModuleLoader::GetCodeCache); | ||
| 325 | 320 | // internalBinding('native_module') should be frozen | |
| 326 | 321 | target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust(); | |
| 327 | 322 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments