From 089e287c6e95edab56e610f7a615933e42aaff52 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 6 Nov 2011 01:11:38 +0100 Subject: [PATCH] compilation cache: fixed recently introduced bug (lazy loading of bodies) --- compiler/nversion.nim | 2 +- compiler/rodread.nim | 39 +++++++++++++++++++++++++----------- compiler/rodwrite.nim | 10 ++++----- tests/rodfiles/tgeneric1.nim | 13 ++++++++++++ tests/rodfiles/tgeneric2.nim | 13 ++++++++++++ tests/tester.nim | 4 ++++ todo.txt | 1 - 7 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 tests/rodfiles/tgeneric1.nim create mode 100644 tests/rodfiles/tgeneric2.nim diff --git a/compiler/nversion.nim b/compiler/nversion.nim index a913073004..b0a40f2049 100755 --- a/compiler/nversion.nim +++ b/compiler/nversion.nim @@ -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! diff --git a/compiler/rodread.nim b/compiler/rodread.nim index 900361ed7c..6301031e94 100755 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -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 diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index d217d17407..ee56ec0a9c 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -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: diff --git a/tests/rodfiles/tgeneric1.nim b/tests/rodfiles/tgeneric1.nim new file mode 100644 index 0000000000..a3f7b870bb --- /dev/null +++ b/tests/rodfiles/tgeneric1.nim @@ -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] + diff --git a/tests/rodfiles/tgeneric2.nim b/tests/rodfiles/tgeneric2.nim new file mode 100644 index 0000000000..552d60267a --- /dev/null +++ b/tests/rodfiles/tgeneric2.nim @@ -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] + diff --git a/tests/tester.nim b/tests/tester.nim index 071561b301..9bf16d84d8 100755 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -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 = diff --git a/todo.txt b/todo.txt index a38bb8c960..c62301394d 100755 --- a/todo.txt +++ b/todo.txt @@ -7,7 +7,6 @@ Version 0.8.14 - fix actors.nim; test with different thread var implementations - dead code elim for JS backend - version 0.9.0 =============