summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-10-23 11:24:52 +0200
committerAraq <rumpf_a@web.de>2011-10-23 11:24:52 +0200
commitbd1cb9e77befaab83a4d78d9211480cc7ee1b95b (patch)
tree8a86b0d94443c24aabd0625aeee76fc3efa89f6b /compiler
parent2b323c638c6aed9f3b441c4b33316a80cc1da6e6 (diff)
downloadNim-bd1cb9e77befaab83a4d78d9211480cc7ee1b95b.tar.gz
compilation cache: methods have a chance to work
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ccgthreadvars.nim16
-rwxr-xr-xcompiler/rodread.nim49
-rwxr-xr-xcompiler/rodwrite.nim16
-rwxr-xr-xcompiler/transf.nim10
4 files changed, 69 insertions, 22 deletions
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index 7ef084ba8..0f3661010 100755
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -8,7 +8,7 @@
 #
 
 ## Thread var support for crappy architectures that lack native support for 
-## thread local storage.
+## thread local storage. (**Thank you Mac OS X!**)
 
 proc emulatedThreadVars(): bool {.inline.} =
   result = optThreads in gGlobalOptions
@@ -23,9 +23,17 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) =
     appcg(p, cpsInit, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n")
 
 var
-  nimtv: PRope # nimrod thread vars
-  nimtvDeps: seq[PType] = @[]
-  nimtvDeclared = initIntSet()
+  nimtv: PRope                 # nimrod thread vars; the struct body
+  nimtvDeps: seq[PType] = @[]  # type deps: every module needs whole struct
+  nimtvDeclared = initIntSet() # so that every var/field exists only once
+                               # in the struct
+
+# 'nimtv' is incredibly hard to modularize! Best effort is to store all thread
+# vars in a ROD section and with their type deps and load them
+# unconditionally...
+
+# nimtvDeps is VERY hard to cache because it's not a list of IDs nor can it be
+# made to be one.
 
 proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
   if emulatedThreadVars():
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index 6191218fe..baffac4c4 100755
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -9,10 +9,11 @@
 
 # This module is responsible for loading of rod files.
 #
-#  Reading and writing binary files are really hard to debug. Therefore we use
-#  a special text format. ROD-files are more efficient to process because
-#  symbols are only loaded on demand.
-#  It consists of:
+# Reading and writing binary files are really hard to debug. Therefore we use
+# a "creative" text/binary hybrid format. ROD-files are more efficient
+# to process because symbols are can be loaded on demand.
+# 
+# A ROD file consists of:
 #
 #  - a header:
 #    NIM:$fileversion\n
@@ -28,7 +29,7 @@
 #    myfile.inc
 #    lib/mymodA
 #    )
-#  - a include file dependency section:
+#  - an include file dependency section:
 #    INCLUDES(
 #    <fileidx> <CRC of myfile.inc>\n # fileidx is the LINE in the file section!
 #    )
@@ -48,6 +49,11 @@
 #    id-diff idx-diff\n
 #    id-diff idx-diff\n
 #    )
+#
+#    Since the whole index has to be read in advance, we compress it by 
+#    storing the integer differences to the last entry instead of using the
+#    real numbers.
+#
 #  - an import index consisting of (ID, moduleID)-pairs:
 #    IMPORTS(
 #    id-diff moduleID-diff\n
@@ -55,7 +61,12 @@
 #    )
 #  - a list of all exported type converters because they are needed for correct
 #    semantic checking:
-#    CONVERTERS:id id\n   # position of the symbol in the DATA section
+#    CONVERTERS:id id\n   # symbol ID
+#
+#  - a list of all (private or exported) methods because they are needed for
+#    correct dispatcher generation:
+#    METHODS: id id\n   # symbol ID
+#
 #  - an AST section that contains the module's AST:
 #    INIT(
 #    idx\n  # position of the node in the DATA section
@@ -72,8 +83,6 @@
 #    stops immediately after ``DATA(`` and the rest is only loaded on demand
 #    by using mem'mapped a file.
 #
-#  We now also do index compression, because an index always needs to be read.
-#
 
 import 
   os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, 
@@ -116,7 +125,7 @@ type
     files: TStringSeq
     dataIdx: int             # offset of start of data section
     convertersIdx: int       # offset of start of converters section
-    initIdx, interfIdx, compilerProcsIdx: int
+    initIdx, interfIdx, compilerProcsIdx, methodsIdx: int
     filename: string
     index, imports: TIndex
     readerIndex: int
@@ -125,6 +134,7 @@ type
     syms: TIdTable       # already processed symbols
     memfile: TMemFile    # unfortunately there is no point in time where we
                          # can close this! XXX
+    methods*: TSymSeq
   
   PRodReader* = ref TRodReader
 
@@ -547,6 +557,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
     of "CONVERTERS": 
       r.convertersIdx = r.pos + 1
       skipSection(r)
+    of "METHODS":
+      r.methodsIdx = r.pos + 1
+      skipSection(r)
     of "DATA": 
       r.dataIdx = r.pos + 2 # "(\10"
       # We do not read the DATA section here! We read the needed objects on
@@ -573,6 +586,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
   new(result)
   result.files = @[]
   result.modDeps = @[]
+  result.methods = @[]
   var r = result
   r.reason = rrNone
   r.pos = 0
@@ -599,7 +613,7 @@ proc newRodReader(modfilename: string, crc: TCrc32,
       processRodFile(r, crc)
     else: 
       result = nil
-  else: 
+  else:
     result = nil
   
 proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = 
@@ -681,7 +695,8 @@ proc loadInitSection(r: PRodReader): PNode =
   r.pos = oldPos
 
 proc loadConverters(r: PRodReader) = 
-  # We have to ensure that no exported converter is a stub anymore.
+  # We have to ensure that no exported converter is a stub anymore, and the
+  # import mechanism takes care of the rest.
   if r.convertersIdx == 0 or r.dataIdx == 0: 
     InternalError("importConverters")
   r.pos = r.convertersIdx
@@ -689,6 +704,15 @@ proc loadConverters(r: PRodReader) =
     var d = decodeVInt(r.s, r.pos)
     discard rrGetSym(r, d, UnknownLineInfo())
     if r.s[r.pos] == ' ': inc(r.pos)
+
+proc loadMethods(r: PRodReader) =
+  if r.methodsIdx == 0 or r.dataIdx == 0:
+    InternalError("loadMethods")
+  r.pos = r.methodsIdx
+  while r.s[r.pos] > '\x0A':
+    var d = decodeVInt(r.s, r.pos)
+    r.methods.add(rrGetSym(r, d, UnknownLineInfo()))
+    if r.s[r.pos] == ' ': inc(r.pos)
   
 proc getModuleIdx(filename: string): int = 
   for i in countup(0, high(gMods)): 
@@ -752,7 +776,8 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
     processInterf(result, module)
     processCompilerProcs(result, module)
     loadConverters(result)
-  else: 
+    loadMethods(result)
+  else:
     module.id = getID()
   
 proc GetCRC*(filename: string): TCrc32 = 
diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim
index 719bdde14..b735aee6a 100755
--- a/compiler/rodwrite.nim
+++ b/compiler/rodwrite.nim
@@ -29,7 +29,7 @@ type
     interf: string
     compilerProcs: string
     index, imports: TIndex
-    converters: string
+    converters, methods: string
     init: string
     data: string
     filename: string
@@ -85,6 +85,7 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter =
   result.interf = newStringOfCap(2_000)
   result.compilerProcs = ""
   result.converters = ""
+  result.methods = ""
   result.init = ""
   result.data = newStringOfCap(12_000)
   
@@ -350,6 +351,9 @@ proc symStack(w: PRodWriter) =
         if s.kind == skConverter: 
           if w.converters.len != 0: add(w.converters, ' ')
           encodeVInt(s.id, w.converters)
+        elif s.kind == skMethod:
+          if w.methods.len != 0: add(w.methods, ' ')
+          encodeVInt(s.id, w.methods)
       elif IiTableGet(w.imports.tab, s.id) == invalidKey: 
         addToIndex(w.imports, s.id, m.id) #if not Contains(debugWritten, s.id):
                                           #  MessageOut(w.filename);
@@ -455,6 +459,10 @@ proc writeRod(w: PRodWriter) =
   f.write("CONVERTERS:")
   f.write(w.converters)
   f.write(rodNL)
+
+  f.write("METHODS:")
+  f.write(w.methods)
+  f.write(rodNL)
   
   f.write("INIT(" & rodNL)
   f.write(w.init)
@@ -486,10 +494,10 @@ proc process(c: PPassContext, n: PNode): PNode =
   of nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef: 
     var s = n.sons[namePos].sym
     if s == nil: InternalError(n.info, "rodwrite.process")
-    if (n.sons[codePos].kind != nkEmpty) or (s.magic != mNone) or
-        not (sfForward in s.flags): 
+    if n.sons[codePos].kind != nkEmpty or s.magic != mNone or
+        sfForward notin s.flags:
       addInterfaceSym(w, s)
-  of nkVarSection: 
+  of nkVarSection:
     for i in countup(0, sonsLen(n) - 1): 
       var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9c67165e3..0fb3dd2c6 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -18,7 +18,7 @@
 
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
-  idents, renderer, types, passes, semfold, magicsys, cgmeth
+  idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread
 
 const 
   genPrefix* = ":tmp"         # prefix for generated names
@@ -726,7 +726,7 @@ proc processTransf(context: PPassContext, n: PNode): PNode =
   # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip
   # this step! We have to rely that the semantic pass transforms too errornous
   # nodes into an empty node.
-  if passes.skipCodegen(n): return n
+  if passes.skipCodegen(n) or context.fromCache: return n
   var c = PTransf(context)
   pushTransCon(c, newTransCon(getCurrOwner(c)))
   result = PNode(transform(c, n))
@@ -739,9 +739,15 @@ proc openTransf(module: PSym, filename: string): PPassContext =
   n.module = module
   result = n
 
+proc openTransfCached(module: PSym, filename: string, 
+                      rd: PRodReader): PPassContext = 
+  result = openTransf(module, filename)
+  for m in items(rd.methods): methodDef(m)
+
 proc transfPass(): TPass = 
   initPass(result)
   result.open = openTransf
+  result.openCached = openTransfCached
   result.process = processTransf
   result.close = processTransf # we need to process generics too!