improvements on the hot code reloading support (#10892)

* calling the "_actual" versions of functions when defined within the same module - slowdown for the snappy compression is now down from x6 to x4-x5 when HCR is ON
* dynamically linking to the runtime for VS when HCR is on - binaries are smaller
* compilerProcs are also called using the _actual direct version within the module they are defined (system)!
* updated comments & goals
* handling VS-compatible compilers on Windows in a cleaner way
* now the .dll/.so files end up in the nimcache even when --nimcache isn't explicitly stated
This commit is contained in:
Viktor Kirilov
2019-03-23 15:48:47 +02:00
committed by Andreas Rumpf
parent 0b2a3f6f7f
commit f8146dfd84
7 changed files with 42 additions and 16 deletions

View File

@@ -174,6 +174,11 @@ template genParamLoop(params) {.dirty.} =
if params != nil: add(params, ~", ")
add(params, genArgNoParam(p, ri.sons[i]))
proc addActualPrefixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and
(sym.typ.callConv == ccInline or sym.owner.id == module.id):
res = res & "_actual".rope
proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
# this is a hotspot in the compiler
@@ -186,7 +191,10 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var length = sonsLen(ri)
for i in countup(1, length - 1):
genParamLoop(params)
fixupCall(p, le, ri, d, rdLoc(op), params)
var callee = rdLoc(op)
if p.hcrOn and ri.sons[0].kind == nkSym:
callee.addActualPrefixForHCR(p.module.module, ri.sons[0].sym)
fixupCall(p, le, ri, d, callee, params)
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =

View File

@@ -706,6 +706,8 @@ proc cgsym(m: BModule, name: string): Rope =
# we're picky here for the system module too:
rawMessage(m.config, errGenerated, "system module needs: " & name)
result = sym.loc.r
if m.hcrOn and sym != nil and sym.kind in skProc..skIterator:
result.addActualPrefixForHCR(m.module, sym)
proc generateHeaders(m: BModule) =
add(m.s[cfsHeaders], "\L#include \"nimbase.h\"\L")

View File

@@ -494,6 +494,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if conf.hcrOn:
defineSymbol(conf.symbols, "hotcodereloading")
defineSymbol(conf.symbols, "useNimRtl")
# hardcoded linking with dynamic runtime for MSVC for smaller binaries
# should do the same for all compilers (wherever applicable)
if isVSCompatible(conf):
extccomp.addCompileOptionCmd(conf, "/MD")
else:
undefSymbol(conf.symbols, "hotcodereloading")
undefSymbol(conf.symbols, "useNimRtl")

View File

@@ -223,7 +223,6 @@ compiler bcc:
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
hasAttribute})
# Digital Mars C Compiler
compiler dmc:
result = (
@@ -376,6 +375,11 @@ proc nameToCC*(name: string): TSystemCC =
return i
result = ccNone
proc isVSCompatible*(conf: ConfigRef): bool =
return conf.cCompiler == ccVcc or
conf.cCompiler == ccClangCl or
(conf.cCompiler == ccIcl and conf.target.hostOS in osDos..osWindows)
proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
# use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
# for niminst support
@@ -734,8 +738,9 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# way of being able to debug and rebuild the program at the same time. This
# is accomplished using the /PDB:<filename> flag (there also exists the
# /PDBALTPATH:<filename> flag). The only downside is that the .pdb files are
# atleast 5-10mb big and will quickly accumulate. There is a hacky solution:
# we could try to delete all .pdb files with a pattern and swallow exceptions.
# atleast 300kb big (when linking statically to the runtime - or else 5mb+)
# and will quickly accumulate. There is a hacky solution: we could try to
# delete all .pdb files with a pattern and swallow exceptions.
#
# links about .pdb files and hot code reloading:
# https://ourmachinery.com/post/dll-hot-reloading-in-theory-and-practice/
@@ -747,7 +752,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# and a bit about the .pdb format in case that is ever needed:
# https://github.com/crosire/blink
# http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles
if conf.hcrOn and conf.cCompiler == ccVcc:
if conf.hcrOn and isVSCompatible(conf):
let t = now()
let pdb = output.string & "." & format(t, "MMMM-yyyy-HH-mm-") & $t.nanosecond & ".pdb"
result.add " /link /PDB:" & pdb
@@ -838,7 +843,7 @@ proc hcrLinkTargetName(conf: ConfigRef, objFile: string, isMain = false): Absolu
let basename = splitFile(objFile).name
let targetName = if isMain: basename & ".exe"
else: platform.OS[conf.target.targetOS].dllFrmt % basename
result = conf.nimcacheDir / RelativeFile(targetName)
result = conf.getNimcacheDir / RelativeFile(targetName)
proc callCCompiler*(conf: ConfigRef) =
var
@@ -883,7 +888,7 @@ proc callCCompiler*(conf: ConfigRef) =
add(cmds, getLinkCmd(conf, linkTarget, objfiles & " " & quoteShell(objFile), buildDll))
# try to remove all .pdb files for the current binary so they don't accumulate endlessly in the nimcache
# for more info check the comment inside of getLinkCmd() where the /PDB:<filename> MSVC flag is used
if conf.cCompiler == ccVcc:
if isVSCompatible(conf):
for pdb in walkFiles(objFile & ".*.pdb"):
discard tryRemoveFile(pdb)
# execute link commands in parallel - output will be a bit different