summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-04-20 12:10:23 +0200
committerAraq <rumpf_a@web.de>2014-04-20 12:10:23 +0200
commitc80d563afb7e095b6e9ca4353fb02ae7586ed500 (patch)
treea74368af07770442ad1c33c49adbf9ced002cbb6
parent13b941d8eebbaf64ea69873d131569c78de2529d (diff)
downloadNim-c80d563afb7e095b6e9ca4353fb02ae7586ed500.tar.gz
actors compile again
-rw-r--r--compiler/lowerings.nim1
-rw-r--r--compiler/sempass2.nim6
-rw-r--r--compiler/sigmatch.nim3
-rw-r--r--compiler/types.nim7
-rw-r--r--lib/system.nim17
-rw-r--r--lib/system/assign.nim13
-rw-r--r--lib/system/channels.nim23
-rw-r--r--lib/system/repr.nim8
-rw-r--r--lib/system/sysspawn.nim20
9 files changed, 68 insertions, 30 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 0ca07e828..efa3109c5 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -162,6 +162,7 @@ proc wrapProcForSpawn*(owner: PSym; n: PNode): PNode =
     argsParam.typ = ptrType
     argsParam.position = 1
   var objType = createObj(owner, n.info)
+  incl(objType.flags, tfFinal)
   let castExpr = createCastExpr(argsParam, objType)
 
   var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index b2b91490c..72666e47d 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -71,7 +71,7 @@ type
     init: seq[int] # list of initialized variables
     guards: TModel # nested guards
     locked: seq[PNode] # locked locations
-    gcUnsafe: bool
+    gcUnsafe, isRecursive: bool
   PEffects = var TEffects
 
 proc isLocalVar(a: PEffects, s: PSym): bool =
@@ -502,7 +502,9 @@ proc track(tracked: PEffects, n: PNode) =
     # are indistinguishable from normal procs (both have tyProc type) and
     # we can detect them only by checking for attached nkEffectList.
     if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList:
-      if notGcSafe(op) and not importedFromC(a):
+      if a.kind == nkSym and a.sym == tracked.owner:
+        tracked.isRecursive = true
+      elif notGcSafe(op) and not importedFromC(a):
         message(n.info, warnGcUnsafe, renderTree(n))
         tracked.gcUnsafe = true
       var effectList = op.n.sons[0]
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 5d3ed05f7..673c7f083 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -148,6 +148,9 @@ proc sumGeneric(t: PType): int =
       result = ord(t.kind == tyGenericInvokation)
       for i in 0 .. <t.len: result += t.sons[i].sumGeneric
       break
+    of tyProc:
+      # proc matche proc better than 'stmt' to disambiguate 'spawn'
+      return 1
     of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
     else: return 0
 
diff --git a/compiler/types.nim b/compiler/types.nim
index 1de0fc103..e0e0162ec 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -342,9 +342,10 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
       result = t.id == startId
     # Inheritance can introduce cyclic types, however this is not relevant
     # as the type that is passed to 'new' is statically known!
-    #if t.kind == tyObject and tfFinal notin t.flags:
-    #  # damn inheritance may introduce cycles:
-    #  result = true
+    # er but we use it also for the write barrier ...
+    if t.kind == tyObject and tfFinal notin t.flags:
+      # damn inheritance may introduce cycles:
+      result = true
   of tyProc: result = typ.callConv == ccClosure
   else: discard
 
diff --git a/lib/system.nim b/lib/system.nim
index 3c342cf9a..60d9c5453 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2018,7 +2018,7 @@ when not defined(sysFatal):
       e.msg = message & arg
       raise e
 
-proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo".}
+proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe.}
   ## get type information for `x`. Ordinary code should not use this, but
   ## the `typeinfo` module instead.
 
@@ -2209,10 +2209,14 @@ when not defined(JS): #and not defined(NimrodVM):
       ## Returns ``false`` if the end of the file has been reached, ``true``
       ## otherwise. If ``false`` is returned `line` contains no new data.
 
-    proc writeln*[Ty](f: TFile, x: varargs[Ty, `$`]) {.inline, 
-                             tags: [FWriteIO].}
-      ## writes the values `x` to `f` and then writes "\n".
-      ## May throw an IO exception.
+    when not defined(booting):
+      proc writeln*[Ty](f: TFile, x: varargs[Ty, `$`]) {.inline, 
+                               tags: [FWriteIO], gcsafe.}
+        ## writes the values `x` to `f` and then writes "\n".
+        ## May throw an IO exception.
+    else:
+      proc writeln*[Ty](f: TFile, x: varargs[Ty, `$`]) {.inline, 
+                               tags: [FWriteIO].}
 
     proc getFileSize*(f: TFile): int64 {.tags: [FReadIO], gcsafe.}
       ## retrieves the file size (in bytes) of `f`.
@@ -2935,3 +2939,6 @@ when not defined(booting):
 
   template isStatic*(x): expr = compiles(static(x))
     # checks whether `x` is a value known at compile-time
+
+when hasThreadSupport:
+  when hostOS != "standalone": include "system/sysspawn"
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index bed8820be..75c749633 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -7,10 +7,11 @@
 #    distribution, for details about the copyright.
 #
 
-proc genericResetAux(dest: pointer, n: ptr TNimNode)
+proc genericResetAux(dest: pointer, n: ptr TNimNode) {.gcsafe.}
 
-proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool)
-proc genericAssignAux(dest, src: pointer, n: ptr TNimNode, shallow: bool) =
+proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.gcsafe.}
+proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
+                      shallow: bool) {.gcsafe.} =
   var
     d = cast[TAddress](dest)
     s = cast[TAddress](src)
@@ -139,8 +140,8 @@ proc genericAssignOpenArray(dest, src: pointer, len: int,
     genericAssign(cast[pointer](d +% i*% mt.base.size),
                   cast[pointer](s +% i*% mt.base.size), mt.base)
 
-proc objectInit(dest: pointer, typ: PNimType) {.compilerProc.}
-proc objectInitAux(dest: pointer, n: ptr TNimNode) =
+proc objectInit(dest: pointer, typ: PNimType) {.compilerProc, gcsafe.}
+proc objectInitAux(dest: pointer, n: ptr TNimNode) {.gcsafe.} =
   var d = cast[TAddress](dest)
   case n.kind
   of nkNone: sysAssert(false, "objectInitAux")
@@ -184,7 +185,7 @@ else:
     mixin destroy
     for i in countup(0, r.len - 1): destroy(r[i])
 
-proc genericReset(dest: pointer, mt: PNimType) {.compilerProc.}
+proc genericReset(dest: pointer, mt: PNimType) {.compilerProc, gcsafe.}
 proc genericResetAux(dest: pointer, n: ptr TNimNode) =
   var d = cast[TAddress](dest)
   case n.kind
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index bf949529b..2e66680ef 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -1,7 +1,7 @@
 #

 #

 #            Nimrod's Runtime Library

-#        (c) Copyright 2012 Andreas Rumpf

+#        (c) Copyright 2014 Andreas Rumpf

 #

 #    See the file "copying.txt", included in this

 #    distribution, for details about the copyright.

@@ -49,9 +49,9 @@ proc deinitRawChannel(p: pointer) =
   deinitSysCond(c.cond)

 

 proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, 

-              mode: TLoadStoreMode)

+              mode: TLoadStoreMode) {.gcsafe.}

 proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,

-              mode: TLoadStoreMode) =

+              mode: TLoadStoreMode) {.gcsafe.} =

   var

     d = cast[TAddress](dest)

     s = cast[TAddress](src)

@@ -209,7 +209,6 @@ proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =
 

 proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =

   # to save space, the generic is as small as possible

-  acquireSys(q.lock)

   q.ready = true

   while q.count <= 0:

     waitSysCond(q.cond, q.lock)

@@ -218,17 +217,29 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
     releaseSys(q.lock)

     sysFatal(EInvalidValue, "cannot receive message of wrong type")

   rawRecv(q, res, typ)

-  releaseSys(q.lock)

 

 proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =

   ## receives a message from the channel `c`. This blocks until

   ## a message has arrived! You may use ``peek`` to avoid the blocking.

   var q = cast[PRawChannel](addr(c))

+  acquireSys(q.lock)

   llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

+  releaseSys(q.lock)

+
+proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool,
+                                                  msg: TMsg] =
+  ## try to receives a message from the channel `c` if available. Otherwise
+  ## it returns ``(false, default(msg))``.
+  var q = cast[PRawChannel](addr(c))

+  if q.mask != ChannelDeadMask:

+    lockChannel(q):

+      llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
+      result.dataAvaliable = true

 

 proc peek*[TMsg](c: var TChannel[TMsg]): int =

   ## returns the current number of messages in the channel `c`. Returns -1

-  ## if the channel has been closed.

+  ## if the channel has been closed. **Note**: This is dangerous to use
+  ## as it encourages races. It's much better to use ``tryRecv`` instead.

   var q = cast[PRawChannel](addr(c))

   if q.mask != ChannelDeadMask:

     lockChannel(q):

diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index 7c1a68bc7..487bac052 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -10,7 +10,7 @@
 # The generic ``repr`` procedure. It is an invaluable debugging tool.
 
 when not defined(useNimRtl):
-  proc reprAny(p: pointer, typ: PNimType): string {.compilerRtl.}
+  proc reprAny(p: pointer, typ: PNimType): string {.compilerRtl, gcsafe.}
 
 proc reprInt(x: int64): string {.compilerproc.} = return $x
 proc reprFloat(x: float): string {.compilerproc.} = return $x
@@ -78,7 +78,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
 type
   PByteArray = ptr array[0.. 0xffff, int8]
 
-proc addSetElem(result: var string, elem: int, typ: PNimType) =
+proc addSetElem(result: var string, elem: int, typ: PNimType) {.gcsafe.} =
   case typ.kind
   of tyEnum: add result, reprEnum(elem, typ)
   of tyBool: add result, reprBool(bool(elem))
@@ -147,7 +147,7 @@ when not defined(useNimRtl):
     for i in 0..cl.indent-1: add result, ' '
 
   proc reprAux(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure)
+               cl: var TReprClosure) {.gcsafe.}
 
   proc reprArray(result: var string, p: pointer, typ: PNimType,
                  cl: var TReprClosure) =
@@ -172,7 +172,7 @@ when not defined(useNimRtl):
     add result, "]"
 
   proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
-                     cl: var TReprClosure) =
+                     cl: var TReprClosure) {.gcsafe.} =
     case n.kind
     of nkNone: sysAssert(false, "reprRecordAux")
     of nkSlot:
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 3a641aba6..0a56d6844 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -1,7 +1,18 @@
-# Implements Nimrod's 'spawn'.
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Implements Nimrod's 'spawn'.
+
+when not defined(NimString): 
+  {.error: "You must not import this module explicitly".}
 
 {.push stackTrace:off.}
-include system.syslocks
 
 when (defined(x86) or defined(amd64)) and defined(gcc):
   proc cpuRelax {.inline.} =
@@ -10,12 +21,12 @@ elif (defined(x86) or defined(amd64)) and defined(vcc):
   proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
 elif defined(intelc):
   proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
-else:
+elif false:
   from os import sleep
 
   proc cpuRelax {.inline.} = os.sleep(1)
 
-when defined(windows):
+when defined(windows) and not defined(gcc):
   proc interlockedCompareExchange(p: pointer; exchange, comparand: int32): int32
     {.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.}
 
@@ -70,6 +81,7 @@ proc await(cv: var FastCondVar) =
   #    return
   #  cpuRelax()
   #cv.slowPath = true
+  # XXX For some reason this crashes some test programs
   await(cv.slow)
   cv.event = false