remove any traces of the old global generics cache

This commit is contained in:
Zahary Karadjov 2013-01-27 21:28:34 +02:00
commit 55f8ed2452
6 changed files with 65 additions and 109 deletions

View file

@ -282,7 +282,6 @@ proc CommandCompileToC =
# rodread.gMods # rodread.gMods
# !! ropes.cache # !! ropes.cache
# !! semdata.gGenericsCache
# semthreads.computed? # semthreads.computed?
# #
# suggest.usageSym # suggest.usageSym
@ -397,7 +396,6 @@ proc resetMemory =
ResetAllModules() ResetAllModules()
resetRopeCache() resetRopeCache()
resetSysTypes() resetSysTypes()
gGenericsCache = nil
gOwners = @[] gOwners = @[]
rangeDestructorProc = nil rangeDestructorProc = nil
for i in low(buckets)..high(buckets): for i in low(buckets)..high(buckets):
@ -421,7 +419,6 @@ proc resetMemory =
# rodread.gMods # rodread.gMods
# !! ropes.cache # !! ropes.cache
# !! semdata.gGenericsCache
# semthreads.computed? # semthreads.computed?
# #
# suggest.usageSym # suggest.usageSym

View file

@ -188,15 +188,15 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
include semtypes, semtempl, semgnrc, semstmts, semexprs include semtypes, semtempl, semgnrc, semstmts, semexprs
proc addCodeForGenerics(c: PContext, n: PNode) = proc addCodeForGenerics(c: PContext, n: PNode) =
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1): for i in countup(c.lastGenericIdx, c.generics.len - 1):
var prc = c.generics.generics[i].inst.sym var prc = c.generics[i].inst.sym
if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone:
if prc.ast == nil or prc.ast.sons[bodyPos] == nil: if prc.ast == nil or prc.ast.sons[bodyPos] == nil:
InternalError(prc.info, "no code for " & prc.name.s) InternalError(prc.info, "no code for " & prc.name.s)
else: else:
addSon(n, prc.ast) addSon(n, prc.ast)
c.generics.lastGenericIdx = Len(c.generics.generics) c.lastGenericIdx = c.generics.len
proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} = proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} =
result = semExpr(c, n, {}) result = semExpr(c, n, {})
@ -229,7 +229,7 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = semStmt(c, n) result = semStmt(c, n)
# BUGFIX: process newly generated generics here, not at the end! # BUGFIX: process newly generated generics here, not at the end!
if c.generics.lastGenericIdx < Len(c.generics.generics): if c.lastGenericIdx < c.generics.len:
var a = newNodeI(nkStmtList, n.info) var a = newNodeI(nkStmtList, n.info)
addCodeForGenerics(c, a) addCodeForGenerics(c, a)
if sonsLen(a) > 0: if sonsLen(a) > 0:

View file

@ -39,21 +39,11 @@ type
TInstantiationPair* = object TInstantiationPair* = object
genericSym*: PSym genericSym*: PSym
inst*: PInstantiation inst*: PInstantiation
# If we generate an instance of a generic, we'd like to re-use that
# instance if possible across module boundaries. However, this is not
# possible if the compilation cache is enabled. So we give up then and use
# the caching of generics only per module, not per project.
TGenericsCache* {.final.} = object
generics*: seq[TInstantiationPair] # a list of the things to compile
lastGenericIdx*: int # used for the generics stack
PGenericsCache* = ref TGenericsCache
PContext* = ref TContext PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module TContext* = object of TPassContext # a context represents a module
module*: PSym # the module sym belonging to the context module*: PSym # the module sym belonging to the context
p*: PProcCon # procedure context p*: PProcCon # procedure context
generics*: PGenericsCache # may point to a global or module-local structure
friendModule*: PSym # current friend module; may access private data; friendModule*: PSym # current friend module; may access private data;
# this is used so that generic instantiations # this is used so that generic instantiations
# can access private object fields # can access private object fields
@ -84,9 +74,9 @@ type
evalContext*: PEvalContext evalContext*: PEvalContext
UnknownIdents*: TIntSet # ids of all unknown identifiers to prevent UnknownIdents*: TIntSet # ids of all unknown identifiers to prevent
# naming it multiple times # naming it multiple times
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
var lastGenericIdx*: int # used for the generics stack
gGenericsCache*: PGenericsCache # save for modularity
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s result.genericSym = s
@ -96,10 +86,6 @@ proc filename*(c: PContext): string =
# the module's filename # the module's filename
return c.module.filename return c.module.filename
proc newGenericsCache*(): PGenericsCache =
new(result)
result.generics = @[]
proc newContext*(module: PSym): PContext proc newContext*(module: PSym): PContext
proc lastOptionEntry*(c: PContext): POptionEntry proc lastOptionEntry*(c: PContext): POptionEntry
@ -171,15 +157,7 @@ proc newContext(module: PSym): PContext =
result.patterns = @[] result.patterns = @[]
result.includedFiles = initIntSet() result.includedFiles = initIntSet()
initStrTable(result.userPragmas) initStrTable(result.userPragmas)
if optSymbolFiles notin gGlobalOptions: result.generics = @[]
# re-usage of generic instantiations across module boundaries is
# very nice for code size:
if gGenericsCache == nil: gGenericsCache = newGenericsCache()
result.generics = gGenericsCache
else:
# we have to give up and use a per-module cache for generic instantiations:
result.generics = newGenericsCache()
assert gGenericsCache == nil
result.UnknownIdents = initIntSet() result.UnknownIdents = initIntSet()
proc inclSym(sq: var TSymSeq, s: PSym) = proc inclSym(sq: var TSymSeq, s: PSym) =

View file

@ -1359,7 +1359,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let oldInUnrolledContext = c.InUnrolledContext let oldInUnrolledContext = c.InUnrolledContext
let oldInGenericInst = c.InGenericInst let oldInGenericInst = c.InGenericInst
let oldProcCon = c.p let oldProcCon = c.p
c.generics = newGenericsCache() c.generics = @[]
try: try:
result = semExpr(c, n, flags) result = semExpr(c, n, flags)
if msgs.gErrorCounter != oldErrorCount: result = nil if msgs.gErrorCounter != oldErrorCount: result = nil

View file

@ -104,9 +104,9 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
popProcCon(c) popProcCon(c)
proc fixupInstantiatedSymbols(c: PContext, s: PSym) = proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
for i in countup(0, Len(c.generics.generics) - 1): for i in countup(0, c.generics.len - 1):
if c.generics.generics[i].genericSym.id == s.id: if c.generics[i].genericSym.id == s.id:
var oldPrc = c.generics.generics[i].inst.sym var oldPrc = c.generics[i].inst.sym
pushInfoContext(oldPrc.info) pushInfoContext(oldPrc.info)
openScope(c.tab) openScope(c.tab)
var n = oldPrc.ast var n = oldPrc.ast
@ -166,7 +166,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
var oldPrc = GenericCacheGet(fn, entry[]) var oldPrc = GenericCacheGet(fn, entry[])
if oldPrc == nil: if oldPrc == nil:
fn.procInstCache.safeAdd(entry) fn.procInstCache.safeAdd(entry)
c.generics.generics.add(makeInstPair(fn, entry)) c.generics.add(makeInstPair(fn, entry))
if n.sons[pragmasPos].kind != nkEmpty: if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas) pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
if isNil(n.sons[bodyPos]): if isNil(n.sons[bodyPos]):

View file

@ -42,6 +42,11 @@ proc searchInstTypes(key: PType): PType =
for inst in genericTyp.sym.typeInstCache: for inst in genericTyp.sym.typeInstCache:
if inst.id == key.id: return inst if inst.id == key.id: return inst
if inst.sons.len < key.sons.len:
# XXX: This happens for prematurely cached
# types such as TChannel[empty]. Why?
# See the notes for PActor in handleGenericInvokation
return
block MatchType: block MatchType:
for j in 1 .. high(key.sons): for j in 1 .. high(key.sons):
# XXX sameType is not really correct for nested generics? # XXX sameType is not really correct for nested generics?
@ -138,75 +143,51 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
var body = t.sons[0] var body = t.sons[0]
if body.kind != tyGenericBody: InternalError(cl.info, "no generic body") if body.kind != tyGenericBody: InternalError(cl.info, "no generic body")
var header: PType = nil var header: PType = nil
when true: # search for some instantiation here:
# search for some instantiation here: result = searchInstTypes(t)
result = searchInstTypes(t) if result != nil: return
if result != nil: return for i in countup(1, sonsLen(t) - 1):
for i in countup(1, sonsLen(t) - 1): var x = t.sons[i]
var x = t.sons[i] if x.kind == tyGenericParam:
if x.kind == tyGenericParam: x = lookupTypeVar(cl, x)
x = lookupTypeVar(cl, x) if header == nil: header = copyType(t, t.owner, false)
if header == nil: header = copyType(t, t.owner, false)
header.sons[i] = x
#idTablePut(cl.typeMap, body.sons[i-1], x)
if header != nil:
# search again after first pass:
result = searchInstTypes(header)
if result != nil: return
else:
header = copyType(t, t.owner, false)
# ugh need another pass for deeply recursive generic types (e.g. PActor)
# we need to add the candidate here, before it's fully instantiated for
# recursive instantions:
result = newType(tyGenericInst, t.sons[0].owner)
result.rawAddSon(header.sons[0])
cacheTypeInst(result)
for i in countup(1, sonsLen(t) - 1):
var x = replaceTypeVarsT(cl, t.sons[i])
assert x.kind != tyGenericInvokation
header.sons[i] = x header.sons[i] = x
idTablePut(cl.typeMap, body.sons[i-1], x) #idTablePut(cl.typeMap, body.sons[i-1], x)
if header != nil:
for i in countup(1, sonsLen(t) - 1): # search again after first pass:
# if one of the params is not concrete, we cannot do anything result = searchInstTypes(header)
# but we already raised an error! if result != nil: return
rawAddSon(result, header.sons[i])
var newbody = ReplaceTypeVarsT(cl, lastSon(body))
newbody.flags = newbody.flags + t.flags + body.flags
result.flags = result.flags + newbody.flags
newbody.callConv = body.callConv
newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
# This type may be a generic alias and we want to resolve it here.
# One step is enough, because the recursive nature of
# handleGenericInvokation will handle the alias-to-alias-to-alias case
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
rawAddSon(result, newbody)
checkPartialConstructedType(cl.info, newbody)
else: else:
for i in countup(1, sonsLen(t) - 1): header = copyType(t, t.owner, false)
if PType(idTableGet(cl.typeMap, t.sons[i])) == nil: debug(t) # ugh need another pass for deeply recursive generic types (e.g. PActor)
var x = replaceTypeVarsT(cl, t.sons[i]) # we need to add the candidate here, before it's fully instantiated for
if t.sons[i].kind == tyGenericParam: # recursive instantions:
if header == nil: header = copyType(t, t.owner, false) result = newType(tyGenericInst, t.sons[0].owner)
header.sons[i] = x result.rawAddSon(header.sons[0])
assert x.kind != tyGenericInvokation cacheTypeInst(result)
idTablePut(cl.typeMap, body.sons[i-1], x)
if header == nil: header = t for i in countup(1, sonsLen(t) - 1):
result = searchInstTypes(cl.c.generics.InstTypes, header) var x = replaceTypeVarsT(cl, t.sons[i])
if result != nil: return assert x.kind != tyGenericInvokation
result = newType(tyGenericInst, t.sons[0].owner) header.sons[i] = x
for i in countup(0, sonsLen(t) - 1): idTablePut(cl.typeMap, body.sons[i-1], x)
# if one of the params is not concrete, we cannot do anything
# but we already raised an error! for i in countup(1, sonsLen(t) - 1):
addSon(result, header.sons[i]) # if one of the params is not concrete, we cannot do anything
idTablePut(cl.c.generics.InstTypes, header, result) # but we already raised an error!
var newbody = ReplaceTypeVarsT(cl, lastSon(body)) rawAddSon(result, header.sons[i])
newbody.flags = newbody.flags + t.flags + body.flags
newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n) var newbody = ReplaceTypeVarsT(cl, lastSon(body))
addSon(result, newbody) newbody.flags = newbody.flags + t.flags + body.flags
checkPartialConstructedType(cl.info, newbody) result.flags = result.flags + newbody.flags
newbody.callConv = body.callConv
newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
# This type may be a generic alias and we want to resolve it here.
# One step is enough, because the recursive nature of
# handleGenericInvokation will handle the alias-to-alias-to-alias case
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
rawAddSon(result, newbody)
checkPartialConstructedType(cl.info, newbody)
proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
result = t result = t