mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
compilation cache: fixed recently introduced bug (lazy loading of bodies)
This commit is contained in:
@@ -18,5 +18,5 @@ const
|
||||
VersionPatch* = 13
|
||||
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
|
||||
# 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
|
||||
@@ -91,8 +91,8 @@ import
|
||||
ropes, idents, crc, idgen, rodutils, memfiles
|
||||
|
||||
type
|
||||
TReasonForRecompile* = enum
|
||||
rrEmpty, # used by moddeps module
|
||||
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
|
||||
rrEmpty, # dependencies not yet computed
|
||||
rrNone, # no need to recompile
|
||||
rrRodDoesNotExist, # rod file does not exist
|
||||
rrRodInvalid, # rod file is invalid
|
||||
@@ -146,10 +146,11 @@ var rodCompilerprocs*: TStrTable
|
||||
proc handleSymbolFile*(module: PSym, filename: string): PRodReader
|
||||
# global because this is needed by magicsys
|
||||
proc loadInitSection*(r: PRodReader): PNode
|
||||
proc loadStub*(s: PSym)
|
||||
|
||||
# implementation
|
||||
|
||||
proc rawLoadStub(s: PSym)
|
||||
|
||||
var gTypeTable: TIdTable
|
||||
|
||||
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))
|
||||
inc i
|
||||
if r.s[r.pos] == ')': inc(r.pos)
|
||||
else: internalError(result.info, "decodeNode")
|
||||
else:
|
||||
InternalError(fInfo, "decodeNode " & r.s[r.pos])
|
||||
else: internalError(result.info, "decodeNode: ')' missing")
|
||||
else:
|
||||
InternalError(fInfo, "decodeNode: '(' missing " & $r.pos)
|
||||
|
||||
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
|
||||
result = decodeNodeLazyBody(r, fInfo, nil)
|
||||
@@ -408,7 +409,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||
result.position = decodeVInt(r.s, r.pos)
|
||||
elif result.kind notin routineKinds:
|
||||
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.
|
||||
if r.s[r.pos] == '`':
|
||||
inc(r.pos)
|
||||
@@ -420,6 +421,9 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||
if r.s[r.pos] == '(':
|
||||
if result.kind in routineKinds:
|
||||
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:
|
||||
result.ast = decodeNode(r, result.info)
|
||||
#echo "decoded: ", ident.s, "}"
|
||||
@@ -637,7 +641,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
||||
except EOS:
|
||||
return nil
|
||||
# we terminate the file explicitely with ``\0``, so the cast to `cstring`
|
||||
# is save:
|
||||
# is safe:
|
||||
r.s = cast[cstring](r.memFile.mem)
|
||||
if startsWith(r.s, "NIM:"):
|
||||
initIITable(r.index.tab)
|
||||
@@ -649,7 +653,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
||||
inc(r.pos)
|
||||
if r.s[r.pos] == '\x0A': inc(r.pos)
|
||||
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
|
||||
processRodFile(r, crc)
|
||||
else:
|
||||
@@ -729,7 +733,7 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||
else:
|
||||
# own symbol:
|
||||
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 =
|
||||
if r.initIdx == 0 or r.dataIdx == 0: InternalError("loadInitSection")
|
||||
@@ -835,7 +839,7 @@ proc GetCRC*(filename: string): TCrc32 =
|
||||
var idx = getModuleIdx(filename)
|
||||
result = gMods[idx].crc
|
||||
|
||||
proc loadStub(s: PSym) =
|
||||
proc rawLoadStub(s: PSym) =
|
||||
if s.kind != skStub: InternalError("loadStub")
|
||||
var rd = gMods[s.position].rd
|
||||
var theId = s.id # used for later check
|
||||
@@ -848,6 +852,17 @@ proc loadStub(s: PSym) =
|
||||
InternalError(rs.info, "loadStub: wrong ID")
|
||||
#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 =
|
||||
## 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
|
||||
|
||||
@@ -518,12 +518,12 @@ proc process(c: PPassContext, n: PNode): PNode =
|
||||
if c == nil: return
|
||||
var w = PRodWriter(c)
|
||||
case n.kind
|
||||
of nkStmtList:
|
||||
of nkStmtList:
|
||||
for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
|
||||
of nkTemplateDef, nkMacroDef:
|
||||
var s = n.sons[namePos].sym
|
||||
addInterfaceSym(w, s)
|
||||
of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef:
|
||||
#var s = n.sons[namePos].sym
|
||||
#addInterfaceSym(w, s)
|
||||
of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef,
|
||||
nkTemplateDef, nkMacroDef:
|
||||
var s = n.sons[namePos].sym
|
||||
if s == nil: InternalError(n.info, "rodwrite.process")
|
||||
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"
|
||||
delNimCache()
|
||||
|
||||
# test generics:
|
||||
test "tgeneric1.nim"
|
||||
test "tgeneric2.nim"
|
||||
delNimCache()
|
||||
|
||||
proc compileRodFiles(r: var TResults, options: string) =
|
||||
template test(filename: expr): stmt =
|
||||
|
||||
Reference in New Issue
Block a user