compilation cache: fixed recently introduced bug (lazy loading of bodies)
This commit is contained in:
parent
dc08a033d9
commit
089e287c6e
7 changed files with 63 additions and 19 deletions
|
|
@ -18,5 +18,5 @@ const
|
||||||
VersionPatch* = 13
|
VersionPatch* = 13
|
||||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
||||||
|
|
||||||
RodFileVersion* = "1031" # modify this if the rod-format changes!
|
RodFileVersion* = "1032" # modify this if the rod-format changes!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
#
|
#
|
||||||
# The data section MUST be the last section of the file, because processing
|
# The data section MUST be the last section of the file, because processing
|
||||||
# stops immediately after ``DATA(`` and the rest is only loaded on demand
|
# stops immediately after ``DATA(`` and the rest is only loaded on demand
|
||||||
# by using mem'mapped a file.
|
# by using a mem'mapped file.
|
||||||
#
|
#
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -91,8 +91,8 @@ import
|
||||||
ropes, idents, crc, idgen, rodutils, memfiles
|
ropes, idents, crc, idgen, rodutils, memfiles
|
||||||
|
|
||||||
type
|
type
|
||||||
TReasonForRecompile* = enum
|
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
|
||||||
rrEmpty, # used by moddeps module
|
rrEmpty, # dependencies not yet computed
|
||||||
rrNone, # no need to recompile
|
rrNone, # no need to recompile
|
||||||
rrRodDoesNotExist, # rod file does not exist
|
rrRodDoesNotExist, # rod file does not exist
|
||||||
rrRodInvalid, # rod file is invalid
|
rrRodInvalid, # rod file is invalid
|
||||||
|
|
@ -146,10 +146,11 @@ var rodCompilerprocs*: TStrTable
|
||||||
proc handleSymbolFile*(module: PSym, filename: string): PRodReader
|
proc handleSymbolFile*(module: PSym, filename: string): PRodReader
|
||||||
# global because this is needed by magicsys
|
# global because this is needed by magicsys
|
||||||
proc loadInitSection*(r: PRodReader): PNode
|
proc loadInitSection*(r: PRodReader): PNode
|
||||||
proc loadStub*(s: PSym)
|
|
||||||
|
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
|
proc rawLoadStub(s: PSym)
|
||||||
|
|
||||||
var gTypeTable: TIdTable
|
var gTypeTable: TIdTable
|
||||||
|
|
||||||
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
|
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
|
||||||
|
|
@ -241,9 +242,9 @@ proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
|
||||||
addSonNilAllowed(result, decodeNodeLazyBody(r, result.info, nil))
|
addSonNilAllowed(result, decodeNodeLazyBody(r, result.info, nil))
|
||||||
inc i
|
inc i
|
||||||
if r.s[r.pos] == ')': inc(r.pos)
|
if r.s[r.pos] == ')': inc(r.pos)
|
||||||
else: internalError(result.info, "decodeNode")
|
else: internalError(result.info, "decodeNode: ')' missing")
|
||||||
else:
|
else:
|
||||||
InternalError(fInfo, "decodeNode " & r.s[r.pos])
|
InternalError(fInfo, "decodeNode: '(' missing " & $r.pos)
|
||||||
|
|
||||||
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
||||||
result = decodeNodeLazyBody(r, fInfo, nil)
|
result = decodeNodeLazyBody(r, fInfo, nil)
|
||||||
|
|
@ -408,7 +409,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
result.position = decodeVInt(r.s, r.pos)
|
result.position = decodeVInt(r.s, r.pos)
|
||||||
elif result.kind notin routineKinds:
|
elif result.kind notin routineKinds:
|
||||||
result.position = 0
|
result.position = 0
|
||||||
# BUGFIX: this may have been misused as reader index! But we still
|
# this may have been misused as reader index! But we still
|
||||||
# need it for routines as the body is loaded lazily.
|
# need it for routines as the body is loaded lazily.
|
||||||
if r.s[r.pos] == '`':
|
if r.s[r.pos] == '`':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
|
|
@ -420,6 +421,9 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
if r.s[r.pos] == '(':
|
if r.s[r.pos] == '(':
|
||||||
if result.kind in routineKinds:
|
if result.kind in routineKinds:
|
||||||
result.ast = decodeNodeLazyBody(r, result.info, result)
|
result.ast = decodeNodeLazyBody(r, result.info, result)
|
||||||
|
# since we load the body lazily, we need to set the reader to
|
||||||
|
# be able to reload:
|
||||||
|
result.position = r.readerIndex
|
||||||
else:
|
else:
|
||||||
result.ast = decodeNode(r, result.info)
|
result.ast = decodeNode(r, result.info)
|
||||||
#echo "decoded: ", ident.s, "}"
|
#echo "decoded: ", ident.s, "}"
|
||||||
|
|
@ -637,7 +641,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
||||||
except EOS:
|
except EOS:
|
||||||
return nil
|
return nil
|
||||||
# we terminate the file explicitely with ``\0``, so the cast to `cstring`
|
# we terminate the file explicitely with ``\0``, so the cast to `cstring`
|
||||||
# is save:
|
# is safe:
|
||||||
r.s = cast[cstring](r.memFile.mem)
|
r.s = cast[cstring](r.memFile.mem)
|
||||||
if startsWith(r.s, "NIM:"):
|
if startsWith(r.s, "NIM:"):
|
||||||
initIITable(r.index.tab)
|
initIITable(r.index.tab)
|
||||||
|
|
@ -649,7 +653,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
if r.s[r.pos] == '\x0A': inc(r.pos)
|
if r.s[r.pos] == '\x0A': inc(r.pos)
|
||||||
if version == RodFileVersion:
|
if version == RodFileVersion:
|
||||||
# since ROD files are only for caching, no backwarts compatibility is
|
# since ROD files are only for caching, no backwards compatibility is
|
||||||
# needed
|
# needed
|
||||||
processRodFile(r, crc)
|
processRodFile(r, crc)
|
||||||
else:
|
else:
|
||||||
|
|
@ -729,7 +733,7 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||||
else:
|
else:
|
||||||
# own symbol:
|
# own symbol:
|
||||||
result = decodeSymSafePos(r, d, info)
|
result = decodeSymSafePos(r, d, info)
|
||||||
if result != nil and result.kind == skStub: loadStub(result)
|
if result != nil and result.kind == skStub: rawLoadStub(result)
|
||||||
|
|
||||||
proc loadInitSection(r: PRodReader): PNode =
|
proc loadInitSection(r: PRodReader): PNode =
|
||||||
if r.initIdx == 0 or r.dataIdx == 0: InternalError("loadInitSection")
|
if r.initIdx == 0 or r.dataIdx == 0: InternalError("loadInitSection")
|
||||||
|
|
@ -835,7 +839,7 @@ proc GetCRC*(filename: string): TCrc32 =
|
||||||
var idx = getModuleIdx(filename)
|
var idx = getModuleIdx(filename)
|
||||||
result = gMods[idx].crc
|
result = gMods[idx].crc
|
||||||
|
|
||||||
proc loadStub(s: PSym) =
|
proc rawLoadStub(s: PSym) =
|
||||||
if s.kind != skStub: InternalError("loadStub")
|
if s.kind != skStub: InternalError("loadStub")
|
||||||
var rd = gMods[s.position].rd
|
var rd = gMods[s.position].rd
|
||||||
var theId = s.id # used for later check
|
var theId = s.id # used for later check
|
||||||
|
|
@ -848,6 +852,17 @@ proc loadStub(s: PSym) =
|
||||||
InternalError(rs.info, "loadStub: wrong ID")
|
InternalError(rs.info, "loadStub: wrong ID")
|
||||||
#MessageOut('loaded stub: ' + s.name.s);
|
#MessageOut('loaded stub: ' + s.name.s);
|
||||||
|
|
||||||
|
proc LoadStub*(s: PSym) =
|
||||||
|
## loads the stub symbol `s`.
|
||||||
|
|
||||||
|
# deactivate the GC here because we do a deep recursion and generate no
|
||||||
|
# garbage when restoring parts of the object graph anyway.
|
||||||
|
# Since we die with internal errors if this fails, so no try-finally is
|
||||||
|
# necessary.
|
||||||
|
GC_disable()
|
||||||
|
rawLoadStub(s)
|
||||||
|
GC_enable()
|
||||||
|
|
||||||
proc getBody*(s: PSym): PNode =
|
proc getBody*(s: PSym): PNode =
|
||||||
## retrieves the AST's body of `s`. If `s` has been loaded from a rod-file
|
## retrieves the AST's body of `s`. If `s` has been loaded from a rod-file
|
||||||
## it may perform an expensive reload operation. Otherwise it's a simple
|
## it may perform an expensive reload operation. Otherwise it's a simple
|
||||||
|
|
|
||||||
|
|
@ -518,12 +518,12 @@ proc process(c: PPassContext, n: PNode): PNode =
|
||||||
if c == nil: return
|
if c == nil: return
|
||||||
var w = PRodWriter(c)
|
var w = PRodWriter(c)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkStmtList:
|
of nkStmtList:
|
||||||
for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
|
for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
|
||||||
of nkTemplateDef, nkMacroDef:
|
#var s = n.sons[namePos].sym
|
||||||
var s = n.sons[namePos].sym
|
#addInterfaceSym(w, s)
|
||||||
addInterfaceSym(w, s)
|
of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef,
|
||||||
of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef:
|
nkTemplateDef, nkMacroDef:
|
||||||
var s = n.sons[namePos].sym
|
var s = n.sons[namePos].sym
|
||||||
if s == nil: InternalError(n.info, "rodwrite.process")
|
if s == nil: InternalError(n.info, "rodwrite.process")
|
||||||
if n.sons[bodyPos] == nil:
|
if n.sons[bodyPos] == nil:
|
||||||
|
|
|
||||||
13
tests/rodfiles/tgeneric1.nim
Normal file
13
tests/rodfiles/tgeneric1.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
output: "abcd"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tables
|
||||||
|
|
||||||
|
var x = initTable[int, string]()
|
||||||
|
|
||||||
|
x[2] = "ab"
|
||||||
|
x[5] = "cd"
|
||||||
|
|
||||||
|
echo x[2], x[5]
|
||||||
|
|
||||||
13
tests/rodfiles/tgeneric2.nim
Normal file
13
tests/rodfiles/tgeneric2.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
output: "abef"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tables
|
||||||
|
|
||||||
|
var x = initTable[int, string]()
|
||||||
|
|
||||||
|
x[2] = "ab"
|
||||||
|
x[5] = "ef"
|
||||||
|
|
||||||
|
echo x[2], x[5]
|
||||||
|
|
||||||
|
|
@ -309,6 +309,10 @@ proc runRodFiles(r: var TResults, options: string) =
|
||||||
test "bmethods2.nim"
|
test "bmethods2.nim"
|
||||||
delNimCache()
|
delNimCache()
|
||||||
|
|
||||||
|
# test generics:
|
||||||
|
test "tgeneric1.nim"
|
||||||
|
test "tgeneric2.nim"
|
||||||
|
delNimCache()
|
||||||
|
|
||||||
proc compileRodFiles(r: var TResults, options: string) =
|
proc compileRodFiles(r: var TResults, options: string) =
|
||||||
template test(filename: expr): stmt =
|
template test(filename: expr): stmt =
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -7,7 +7,6 @@ Version 0.8.14
|
||||||
- fix actors.nim; test with different thread var implementations
|
- fix actors.nim; test with different thread var implementations
|
||||||
- dead code elim for JS backend
|
- dead code elim for JS backend
|
||||||
|
|
||||||
|
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue