diff options
author | Araq <rumpf_a@web.de> | 2014-04-20 12:10:23 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-04-20 12:10:23 +0200 |
commit | c80d563afb7e095b6e9ca4353fb02ae7586ed500 (patch) | |
tree | a74368af07770442ad1c33c49adbf9ced002cbb6 | |
parent | 13b941d8eebbaf64ea69873d131569c78de2529d (diff) | |
download | Nim-c80d563afb7e095b6e9ca4353fb02ae7586ed500.tar.gz |
actors compile again
-rw-r--r-- | compiler/lowerings.nim | 1 | ||||
-rw-r--r-- | compiler/sempass2.nim | 6 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 3 | ||||
-rw-r--r-- | compiler/types.nim | 7 | ||||
-rw-r--r-- | lib/system.nim | 17 | ||||
-rw-r--r-- | lib/system/assign.nim | 13 | ||||
-rw-r--r-- | lib/system/channels.nim | 23 | ||||
-rw-r--r-- | lib/system/repr.nim | 8 | ||||
-rw-r--r-- | lib/system/sysspawn.nim | 20 |
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 |