diff --git a/include/hermes/BCGen/HBC/BCProviderFromSrc.h b/include/hermes/BCGen/HBC/BCProviderFromSrc.h index 7a1b72c3229..36263a28ff4 100644 --- a/include/hermes/BCGen/HBC/BCProviderFromSrc.h +++ b/include/hermes/BCGen/HBC/BCProviderFromSrc.h @@ -10,6 +10,7 @@ #include "hermes/BCGen/HBC/BCProvider.h" #include "hermes/BCGen/HBC/Bytecode.h" +#include "hermes/BCGen/HBC/FileAndSourceMapIdCache.h" #include "llvh/ADT/Optional.h" @@ -87,6 +88,12 @@ class BCProviderFromSrc final : public BCProviderBase { /// which reuses SemContext and the IR but makes a new BCProvider. std::shared_ptr semCtx; + /// The file and source map ID cache used for compiling more code into this + /// BytecodeModule. + /// Keep alive between lazy compilation calls to avoid expensive lookups + /// for huge data URLs in sourceMappingURL. + FileAndSourceMapIdCache fileAndSourceMapIdCache; + explicit CompilationData( const BytecodeGenerationOptions &genOptions, const std::shared_ptr &M, @@ -236,6 +243,11 @@ class BCProviderFromSrc final : public BCProviderBase { return compilationData_.semCtx; } + /// \return the FileAndSourceMapIdCache for debug IDs. + FileAndSourceMapIdCache &getFileAndSourceMapIdCache() { + return compilationData_.fileAndSourceMapIdCache; + } + SHA1 getSourceHash() const override { return sourceHash_; }; diff --git a/include/hermes/BCGen/HBC/FileAndSourceMapIdCache.h b/include/hermes/BCGen/HBC/FileAndSourceMapIdCache.h new file mode 100644 index 00000000000..9d846eb75b6 --- /dev/null +++ b/include/hermes/BCGen/HBC/FileAndSourceMapIdCache.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "llvh/ADT/DenseMap.h" + +#include + +namespace hermes::hbc { + +/// The filename ID and source map URL ID of a buffer. +struct FileAndSourceMapId { + /// ID of the filename when added to BytecodeFunctionGenerator. + uint32_t filenameId; + /// ID of the source map URL when added as a file to + /// BytecodeFunctionGenerator. + uint32_t sourceMappingUrlId; +}; + +/// A map from buffer ID to filelname+source map. +/// Looking up filename/sourcemap id for each instruction is pretty slow, +/// so we cache it. +using FileAndSourceMapIdCache = + llvh::SmallDenseMap; + +} // namespace hermes::hbc diff --git a/include/hermes/BCGen/HBC/HBC.h b/include/hermes/BCGen/HBC/HBC.h index 9abbd44fbdc..9447fc7a099 100644 --- a/include/hermes/BCGen/HBC/HBC.h +++ b/include/hermes/BCGen/HBC/HBC.h @@ -54,6 +54,7 @@ bool generateBytecodeFunctionLazy( Module *M, Function *lazyFunc, uint32_t lazyFuncID, + FileAndSourceMapIdCache &debugIdCache, const BytecodeGenerationOptions &options); /// Generates a BytecodeModule from a module \p M, and will return a unique_ptr diff --git a/lib/BCGen/HBC/BytecodeGenerator.cpp b/lib/BCGen/HBC/BytecodeGenerator.cpp index 8229e0147c7..014464ebf86 100644 --- a/lib/BCGen/HBC/BytecodeGenerator.cpp +++ b/lib/BCGen/HBC/BytecodeGenerator.cpp @@ -436,9 +436,6 @@ bool BytecodeModuleGenerator::generateAddedFunctions() { BytecodeOptions &bytecodeOptions = bm_.getBytecodeOptionsMut(); bytecodeOptions.cjsModulesStaticallyResolved = M_->getCJSModulesResolved(); - // Allow reusing the debug cache between functions - FileAndSourceMapIdCache debugCache{}; - M_->assignIndexToVariables(); const uint32_t strippedFunctionNameId = @@ -505,7 +502,7 @@ bool BytecodeModuleGenerator::generateAddedFunctions() { *this, RA, options_, - debugCache, + debugIdCache_, sourceMapGen_, debugInfoGenerator_); if (!func) diff --git a/lib/BCGen/HBC/BytecodeGenerator.h b/lib/BCGen/HBC/BytecodeGenerator.h index 3c315ca964d..08d6ee289d9 100644 --- a/lib/BCGen/HBC/BytecodeGenerator.h +++ b/lib/BCGen/HBC/BytecodeGenerator.h @@ -63,6 +63,9 @@ class BytecodeModuleGenerator { /// This map is populated before instruction selection. LiteralBufferBuilder::LiteralOffsetMapTy literalOffsetMap_{}; + /// The debug ID cache for the module. + FileAndSourceMapIdCache &debugIdCache_; + /// Options controlling bytecode generation. BytecodeGenerationOptions options_; @@ -98,12 +101,14 @@ class BytecodeModuleGenerator { BytecodeModuleGenerator( BytecodeModule &bcModule, Module *M, + FileAndSourceMapIdCache &debugIdCache, BytecodeGenerationOptions options = BytecodeGenerationOptions::defaults(), SourceMapGenerator *sourceMapGen = nullptr, std::unique_ptr baseBCProvider = nullptr) : bm_(bcModule), M_(M), debugInfoGenerator_(bm_.getDebugInfo()), + debugIdCache_(debugIdCache), options_(options), sourceMapGen_(sourceMapGen), baseBCProvider_(std::move(baseBCProvider)) { diff --git a/lib/BCGen/HBC/HBC.cpp b/lib/BCGen/HBC/HBC.cpp index f2b650706a9..bf094cfac7d 100644 --- a/lib/BCGen/HBC/HBC.cpp +++ b/lib/BCGen/HBC/HBC.cpp @@ -31,10 +31,16 @@ std::unique_ptr generateBytecodeModule( std::unique_ptr baseBCProvider) { PerfSection perf("Bytecode Generation"); auto bm = std::make_unique(); + FileAndSourceMapIdCache debugIdCache{}; bool success = BytecodeModuleGenerator{ - *bm, M, options, sourceMapGen, std::move(baseBCProvider)} + *bm, + M, + debugIdCache, + options, + sourceMapGen, + std::move(baseBCProvider)} .generate(entryPoint, segment); return success ? std::move(bm) : nullptr; @@ -45,8 +51,9 @@ bool generateBytecodeFunctionLazy( Module *M, Function *lazyFunc, uint32_t lazyFuncID, + FileAndSourceMapIdCache &debugIdCache, const BytecodeGenerationOptions &options) { - return BytecodeModuleGenerator{bm, M, options, nullptr, nullptr} + return BytecodeModuleGenerator{bm, M, debugIdCache, options, nullptr, nullptr} .generateLazyFunctions(lazyFunc, lazyFuncID); } @@ -56,9 +63,11 @@ std::unique_ptr generateBytecodeModuleForEval( const BytecodeGenerationOptions &options) { PerfSection perf("Bytecode Generation"); auto bm = std::make_unique(); + FileAndSourceMapIdCache debugIdCache{}; - bool success = BytecodeModuleGenerator{*bm, M, options, nullptr, nullptr} - .generateForEval(entryPoint); + bool success = + BytecodeModuleGenerator{*bm, M, debugIdCache, options, nullptr, nullptr} + .generateForEval(entryPoint); return success ? std::move(bm) : nullptr; } @@ -165,6 +174,7 @@ static void compileLazyFunctionWorker(void *argPtr) { M, func, funcID, + provider->getFileAndSourceMapIdCache(), provider->getBytecodeGenerationOptions())) { data->success = false; data->error = outputManager.getErrorString(); diff --git a/lib/BCGen/HBC/ISel.cpp b/lib/BCGen/HBC/ISel.cpp index 176caa94abf..195ddf8d003 100644 --- a/lib/BCGen/HBC/ISel.cpp +++ b/lib/BCGen/HBC/ISel.cpp @@ -452,9 +452,6 @@ inline FileAndSourceMapId HBCISel::obtainFileAndSourceMapId( sourceMappingUrl = sm.getSourceMappingUrl(bufId); } - // Lazily compiled functions ask to strip the source mapping URL because - // it was already encoded in the top level module, and it could be a 1MB+ - // data url that we don't want to duplicate once per function. if (sourceMappingUrl.empty()) { currentSourceMappingUrlId = kInvalidSourceMappingUrlId; } else { diff --git a/lib/BCGen/HBC/ISel.h b/lib/BCGen/HBC/ISel.h index af53c3a9ed9..2c2ab2a5016 100644 --- a/lib/BCGen/HBC/ISel.h +++ b/lib/BCGen/HBC/ISel.h @@ -8,9 +8,7 @@ #ifndef HERMES_BCGEN_HBC_ISEL_H #define HERMES_BCGEN_HBC_ISEL_H -#include "llvh/ADT/DenseMap.h" - -#include +#include "hermes/BCGen/HBC/FileAndSourceMapIdCache.h" namespace hermes { @@ -23,21 +21,6 @@ namespace hbc { class BytecodeFunctionGenerator; class HVMRegisterAllocator; -/// The filename ID and source map URL ID of a buffer. -struct FileAndSourceMapId { - /// ID of the filename when added to BytecodeFunctionGenerator. - uint32_t filenameId; - /// ID of the source map URL when added as a file to - /// BytecodeFunctionGenerator. - uint32_t sourceMappingUrlId; -}; - -/// A map from buffer ID to filelname+source map. -/// Looking up filename/sourcemap id for each instruction is pretty slow, -/// so we cache it. -using FileAndSourceMapIdCache = - llvh::SmallDenseMap; - /// Generate the bytecode stream for the function. void runHBCISel( Function *F,