<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
TL;DR - when linking from a lazily loaded module and using
Linker::LinkOnlyNeeded, bodies of used functions aren't being copied
during linking.<br>
<br>
Previously on one of our products, we would lazily load our runtime
module (around 9000 functions), and link some user module into this
(which is in all practical use cases much smaller). Then, post
linking, we have a pass that runs over the module and rips out all
the un-materialized functions that weren't being used in the
original user module.<br>
<br>
I only just noticed that LinkModules has a flags parameter that can
take a LinkOnlyNeeded flag, which made me wonder if I could reverse
the link order (EG. link from the lazily loaded runtime module into
the user module), set the LinkOnlyNeeded flag, and hey presto, we
wouldn't need to have a cleanup pass that ran afterwards ripping out
functions that weren't used.<br>
<br>
So I tried it, and it failed. Basically any function that was still
to be materialized wasn't getting its body copied over during
linking.<br>
<br>
The only line of code that differs when you set LinkOnlyNeeded is in
LinkModules.cpp -> ModuleLinker::linkIfNeeded:<br>
<br>
<pre>if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration()))
return false;
</pre>
<br>
The isDeclaration() for functions has a call to isMaterializable().<br>
<br>
Things I've tried:<br>
<ul>
<li>If I don't pass LinkOnlyNeeded but still link from the lazily
loaded runtime module into the user module, it works (albeit it
is orders of magnitude slower like we'd expect).</li>
<li>If I don't lazily load the runtime module, it works (but
again, much slower).</li>
<li>I tried doing the linking and then materializing the newly
linked module, but the runtime functions were still missing
their bodies (which implies the information was lost during
linking).<br>
</li>
<li>If I hack the LinkModules.cpp code such that it checks if the
DGV could be materialized, and if so materialize it, before
checking for a declaration again, it works:</li>
</ul>
<pre>
if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration())) {
if (DGV && DGV->isMaterializable())
DGV->materialize();
if (!(DGV && DGV->isDeclaration()))
return false;
}
</pre>
<p>Even with the extra cost of the hack above - this has resulted in
a 2x speedup in our total link time.<br>
</p>
<p>So really here I am wondering - is this expected behaviour? A
bug? And if so how best to go about fixing the issue would be some
grand advice from people more in the know!<br>
</p>
<p>Cheers,<br>
-Neil.<br>
</p>
</body>
</html>