Skip to content

Commit

Permalink
IC: final implementation steps (#16801)
Browse files Browse the repository at this point in the history
* removed dead code
* we need even more laziness for the generic caches
* make it bootstrap on older Nims
* wrote more deserialization code
* IC: replay required methods information
  • Loading branch information
Araq authored Jan 25, 2021
1 parent 0436a7c commit 25745ad
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 105 deletions.
1 change: 0 additions & 1 deletion compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2236,7 +2236,6 @@ proc genSlice(p: BProc; e: PNode; d: var TLoc) =
"'toOpenArray' is only valid within a call expression")

proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
const ToStringProcSlot = -4
let t = e[1].typ.skipTypes(abstractInst+{tyRange})
let toStrProc = getToStringProc(p.module.g.graph, t)
# XXX need to modify this logic for IC.
Expand Down
4 changes: 1 addition & 3 deletions compiler/cgmeth.nim
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
if disp.typ.lockLevel < meth.typ.lockLevel:
disp.typ.lockLevel = meth.typ.lockLevel

proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) =
proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym) =
var witness: PSym
for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
Expand All @@ -182,8 +182,6 @@ proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) =
# create a new dispatcher:
g.methods.add((methods: @[s], dispatcher: createDispatcher(s, g, idgen)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
if witness != nil:
localError(g.config, s.info, "invalid declaration order; cannot attach '" & s.name.s &
"' to method defined here: " & g.config$witness.info)
Expand Down
6 changes: 4 additions & 2 deletions compiler/ic/packed_ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,9 @@ type
flags*: TTypeFlags
types*: seq[PackedItemId]
n*: NodeId
methods*: seq[(int, PackedItemId)]
#nodeflags*: TNodeFlags
sym*: PackedItemId
owner*: PackedItemId
attachedOps*: array[TTypeAttachedOp, PackedItemId]
size*: BiggestInt
align*: int16
paddingAtEnd*: int16
Expand Down Expand Up @@ -111,6 +109,10 @@ type
floats*: BiTable[BiggestFloat]
#config*: ConfigRef

PackedInstantiation* = object
key*, sym*: PackedItemId
concreteTypes*: seq[PackedItemId]

proc `==`*(a, b: SymId): bool {.borrow.}
proc hash*(a: SymId): Hash {.borrow.}

Expand Down
46 changes: 43 additions & 3 deletions compiler/ic/replayer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
## support.

import ".." / [ast, modulegraphs, trees, extccomp, btrees,
msgs, lineinfos, pathutils, options]
msgs, lineinfos, pathutils, options, cgmeth]

import tables

import packed_ast, to_packed_ast, bitabs

proc replayStateChanges*(module: PSym; g: ModuleGraph) =
let list = module.ast
assert list != nil
Expand Down Expand Up @@ -84,6 +86,44 @@ proc replayStateChanges*(module: PSym; g: ModuleGraph) =
else:
internalAssert g.config, false

# of nkMethodDef:
# methodDef(g, n[namePos].sym, fromCache=true)
proc replayGenericCacheInformation*(g: ModuleGraph; module: int) =
## We remember the generic instantiations a module performed
## in order to to avoid the code bloat that generic code tends
## to imply. This is cheaper than deduplication of identical
## generic instantiations. However, deduplication is more
## powerful and general and I hope to implement it soon too
## (famous last words).
assert g.packed[module].status == loaded
for it in g.packed[module].fromDisk.typeInstCache:
let key = translateId(it[0], g.packed, module, g.config)
g.typeInstCache.mgetOrPut(key, @[]).add LazyType(id: FullId(module: module, packed: it[1]), typ: nil)

for it in mitems(g.packed[module].fromDisk.procInstCache):
let key = translateId(it.key, g.packed, module, g.config)
let sym = translateId(it.sym, g.packed, module, g.config)
var concreteTypes = newSeq[FullId](it.concreteTypes.len)
for i in 0..high(it.concreteTypes):
let tmp = translateId(it.concreteTypes[i], g.packed, module, g.config)
concreteTypes[i] = FullId(module: tmp.module, packed: it.concreteTypes[i])

g.procInstCache.mgetOrPut(key, @[]).add LazyInstantiation(
module: module, sym: FullId(module: sym.module, packed: it.sym),
concreteTypes: concreteTypes, inst: nil)

for it in mitems(g.packed[module].fromDisk.methodsPerType):
let key = translateId(it[0], g.packed, module, g.config)
let col = it[1]
let tmp = translateId(it[2], g.packed, module, g.config)
let symId = FullId(module: tmp.module, packed: it[2])
g.methodsPerType.mgetOrPut(key, @[]).add (col, LazySym(id: symId, sym: nil))

for it in mitems(g.packed[module].fromDisk.enumToStringProcs):
let key = translateId(it[0], g.packed, module, g.config)
let tmp = translateId(it[1], g.packed, module, g.config)
let symId = FullId(module: tmp.module, packed: it[1])
g.enumToStringProcs[key] = LazySym(id: symId, sym: nil)

for it in mitems(g.packed[module].fromDisk.methods):
let sym = loadSymFromId(g.config, g.cache, g.packed, module,
PackedItemId(module: LitId(0), item: it))
methodDef(g, g.idgen, sym)
17 changes: 17 additions & 0 deletions compiler/ic/rodfiles.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ type
bodiesSection
symsSection
typesSection
typeInstCacheSection
procInstCacheSection
attachedOpsSection
methodsPerTypeSection
enumToStringProcsSection
aliveSymsSection # beware, this is stored in a `.alivesyms` file.

RodFileError* = enum
Expand Down Expand Up @@ -73,6 +78,12 @@ proc storePrim*[T](f: var RodFile; x: T) =
elif T is tuple:
for y in fields(x):
storePrim(f, y)
elif T is object:
for y in fields(x):
when y is seq:
storeSeq(f, y)
else:
storePrim(f, y)
else:
{.error: "unsupported type for 'storePrim'".}

Expand Down Expand Up @@ -107,6 +118,12 @@ proc loadPrim*[T](f: var RodFile; x: var T) =
elif T is tuple:
for y in fields(x):
loadPrim(f, y)
elif T is object:
for y in fields(x):
when y is seq:
loadSeq(f, y)
else:
loadPrim(f, y)
else:
{.error: "unsupported type for 'loadPrim'".}

Expand Down
81 changes: 63 additions & 18 deletions compiler/ic/to_packed_ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ type
exports*: seq[(LitId, int32)]
reexports*: seq[(LitId, PackedItemId)]
compilerProcs*, trmacros*, converters*, pureEnums*: seq[(LitId, int32)]
methods*: seq[(LitId, PackedItemId, int32)]
methods*: seq[int32]
macroUsages*: seq[(PackedItemId, PackedLineInfo)]

typeInstCache*: seq[(PackedItemId, PackedItemId)]
procInstCache*: seq[PackedInstantiation]
attachedOps*: seq[(TTypeAttachedOp, PackedItemId, PackedItemId)]
methodsPerType*: seq[(PackedItemId, int, PackedItemId)]
enumToStringProcs*: seq[(PackedItemId, PackedItemId)]

sh*: Shared
cfg: PackedConfig

Expand Down Expand Up @@ -160,9 +167,7 @@ proc addPureEnum*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
m.pureEnums.add((nameId, s.itemId.item))

proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
discard "to do"
# c.m.methods.add((nameId, s.itemId.item))
m.methods.add s.itemId.item

proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
Expand Down Expand Up @@ -415,6 +420,17 @@ proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pa
toPackedNode(n[i], ir, c, m)
ir.patch patchPos

proc storeInstantiation*(c: var PackedEncoder; m: var PackedModule; s: PSym; i: PInstantiation) =
var t = newSeq[PackedItemId](i.concreteTypes.len)
for j in 0..high(i.concreteTypes):
t[j] = storeTypeLater(i.concreteTypes[j], c, m)
m.procInstCache.add PackedInstantiation(key: storeSymLater(s, c, m),
sym: storeSymLater(i.sym, c, m),
concreteTypes: t)

proc storeTypeInst*(c: var PackedEncoder; m: var PackedModule; s: PSym; inst: PType) =
m.typeInstCache.add (storeSymLater(s, c, m), storeTypeLater(inst, c, m))

proc addPragmaComputation*(c: var PackedEncoder; m: var PackedModule; n: PNode) =
toPackedNode(n, m.toReplay, c, m)

Expand All @@ -436,20 +452,6 @@ proc toPackedNodeTopLevel*(n: PNode, encoder: var PackedEncoder; m: var PackedMo
toPackedNodeIgnoreProcDefs(n, encoder, m)
flush encoder, m

proc storePrim*(f: var RodFile; x: PackedType) =
for y in fields(x):
when y is seq:
storeSeq(f, y)
else:
storePrim(f, y)

proc loadPrim*(f: var RodFile; x: var PackedType) =
for y in fields(x):
when y is seq:
loadSeq(f, y)
else:
loadPrim(f, y)

proc loadError(err: RodFileError; filename: AbsoluteFile) =
echo "Error: ", $err, "\nloading file: ", filename.string

Expand Down Expand Up @@ -503,6 +505,12 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef
loadSeqSection symsSection, m.sh.syms
loadSeqSection typesSection, m.sh.types

loadSeqSection typeInstCacheSection, m.typeInstCache
loadSeqSection procInstCacheSection, m.procInstCache
loadSeqSection attachedOpsSection, m.attachedOps
loadSeqSection methodsPerTypeSection, m.methodsPerType
loadSeqSection enumToStringProcsSection, m.enumToStringProcs

close(f)
result = f.err

Expand Down Expand Up @@ -557,6 +565,13 @@ proc saveRodFile*(filename: AbsoluteFile; encoder: var PackedEncoder; m: var Pac
storeSeqSection symsSection, m.sh.syms

storeSeqSection typesSection, m.sh.types

storeSeqSection typeInstCacheSection, m.typeInstCache
storeSeqSection procInstCacheSection, m.procInstCache
storeSeqSection attachedOpsSection, m.attachedOps
storeSeqSection methodsPerTypeSection, m.methodsPerType
storeSeqSection enumToStringProcsSection, m.enumToStringProcs

close(f)
if f.err != ok:
storeError(f.err, filename)
Expand Down Expand Up @@ -902,6 +917,36 @@ proc loadProcBody*(config: ConfigRef, cache: IdentCache;
assert pos != emptyNodeId
result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos)

proc loadTypeFromId*(config: ConfigRef, cache: IdentCache;
g: var PackedModuleGraph; module: int; id: PackedItemId): PType =
result = g[module].types[id.item]
if result == nil:
var decoder = PackedDecoder(
lastModule: int32(-1),
lastLit: LitId(0),
lastFile: FileIndex(-1),
config: config,
cache: cache)
result = loadType(decoder, g, module, id)

proc loadSymFromId*(config: ConfigRef, cache: IdentCache;
g: var PackedModuleGraph; module: int; id: PackedItemId): PSym =
result = g[module].syms[id.item]
if result == nil:
var decoder = PackedDecoder(
lastModule: int32(-1),
lastLit: LitId(0),
lastFile: FileIndex(-1),
config: config,
cache: cache)
result = loadSym(decoder, g, module, id)

proc translateId*(id: PackedItemId; g: PackedModuleGraph; thisModule: int; config: ConfigRef): ItemId =
if id.module == LitId(0):
ItemId(module: thisModule.int32, item: id.item)
else:
ItemId(module: toFileIndex(id.module, g[thisModule].fromDisk, config).int32, item: id.item)

proc checkForHoles(m: PackedModule; config: ConfigRef; moduleId: int) =
var bugs = 0
for i in 1 .. high(m.sh.syms):
Expand Down
Loading

0 comments on commit 25745ad

Please sign in to comment.