@@ -1301,6 +1301,69 @@ namespace {
13011301
13021302 JuliaOJIT::ResourcePool<std::unique_ptr<TargetMachine>> TMs;
13031303 };
1304+
1305+ struct JITPointersT {
1306+
1307+ JITPointersT (SharedBytesT &SharedBytes, std::mutex &Lock) JL_NOTSAFEPOINT
1308+ : SharedBytes(SharedBytes), Lock(Lock) {}
1309+
1310+ void operator ()(Module &M) JL_NOTSAFEPOINT {
1311+ std::lock_guard<std::mutex> locked (Lock);
1312+ for (auto &GV : make_early_inc_range (M.globals ())) {
1313+ if (auto *Shared = getSharedBytes (GV)) {
1314+ ++InternedGlobals;
1315+ GV.replaceAllUsesWith (Shared);
1316+ GV.eraseFromParent ();
1317+ }
1318+ }
1319+
1320+ // Windows needs some inline asm to help
1321+ // build unwind tables
1322+ jl_decorate_module (M);
1323+ }
1324+
1325+ private:
1326+ // optimize memory by turning long strings into memoized copies, instead of
1327+ // making a copy per object file of output.
1328+ // we memoize them using a StringSet with a custom-alignment allocator
1329+ // to ensure they are properly aligned
1330+ Constant *getSharedBytes (GlobalVariable &GV) JL_NOTSAFEPOINT {
1331+ // We could probably technically get away with
1332+ // interning even external linkage globals,
1333+ // as long as they have global unnamedaddr,
1334+ // but currently we shouldn't be emitting those
1335+ // except in imaging mode, and we don't want to
1336+ // do this optimization there.
1337+ if (GV.hasExternalLinkage () || !GV.hasGlobalUnnamedAddr ()) {
1338+ return nullptr ;
1339+ }
1340+ if (!GV.hasInitializer ()) {
1341+ return nullptr ;
1342+ }
1343+ if (!GV.isConstant ()) {
1344+ return nullptr ;
1345+ }
1346+ auto CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer ());
1347+ if (!CDS) {
1348+ return nullptr ;
1349+ }
1350+ StringRef Data = CDS->getRawDataValues ();
1351+ if (Data.size () < 16 ) {
1352+ // Cutoff, since we don't want to intern small strings
1353+ return nullptr ;
1354+ }
1355+ Align Required = GV.getAlign ().valueOrOne ();
1356+ Align Preferred = MaxAlignedAlloc::alignment (Data.size ());
1357+ if (Required > Preferred)
1358+ return nullptr ;
1359+ StringRef Interned = SharedBytes.insert (Data).first ->getKey ();
1360+ assert (llvm::isAddrAligned (Preferred, Interned.data ()));
1361+ return literal_static_pointer_val (Interned.data (), GV.getType ());
1362+ }
1363+
1364+ SharedBytesT &SharedBytes;
1365+ std::mutex &Lock;
1366+ };
13041367}
13051368
13061369llvm::DataLayout jl_create_datalayout (TargetMachine &TM) {
@@ -1493,8 +1556,7 @@ void JuliaOJIT::addModule(orc::ThreadSafeModule TSM)
14931556 ++ModulesAdded;
14941557 orc::SymbolLookupSet NewExports;
14951558 TSM.withModuleDo ([&](Module &M) JL_NOTSAFEPOINT {
1496- jl_decorate_module (M);
1497- shareStrings (M);
1559+ JITPointersT (SharedBytes, RLST_mutex)(M);
14981560 for (auto &F : M.global_values ()) {
14991561 if (!F.isDeclaration () && F.getLinkage () == GlobalValue::ExternalLinkage) {
15001562 auto Name = ES.intern (getMangledName (F.getName ()));
@@ -1820,32 +1882,6 @@ void jl_merge_module(orc::ThreadSafeModule &destTSM, orc::ThreadSafeModule srcTS
18201882 });
18211883}
18221884
1823- // optimize memory by turning long strings into memoized copies, instead of
1824- // making a copy per object file of output.
1825- void JuliaOJIT::shareStrings (Module &M)
1826- {
1827- ++InternedGlobals;
1828- std::vector<GlobalVariable*> erase;
1829- for (auto &GV : M.globals ()) {
1830- if (!GV.hasInitializer () || !GV.isConstant ())
1831- continue ;
1832- ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer ());
1833- if (CDS == nullptr )
1834- continue ;
1835- StringRef data = CDS->getRawDataValues ();
1836- if (data.size () > 16 ) { // only for long strings: keep short ones as values
1837- Type *T_size = Type::getIntNTy (GV.getContext (), sizeof (void *) * 8 );
1838- Constant *v = ConstantExpr::getIntToPtr (
1839- ConstantInt::get (T_size, (uintptr_t )(*ES.intern (data)).data ()),
1840- GV.getType ());
1841- GV.replaceAllUsesWith (v);
1842- erase.push_back (&GV);
1843- }
1844- }
1845- for (auto GV : erase)
1846- GV->eraseFromParent ();
1847- }
1848-
18491885// TargetMachine pass-through methods
18501886
18511887std::unique_ptr<TargetMachine> JuliaOJIT::cloneTargetMachine () const
0 commit comments