actors compile again
This commit is contained in:
parent
13b941d8ee
commit
c80d563afb
9 changed files with 68 additions and 30 deletions
|
|
@ -162,6 +162,7 @@ proc wrapProcForSpawn*(owner: PSym; n: PNode): PNode =
|
||||||
argsParam.typ = ptrType
|
argsParam.typ = ptrType
|
||||||
argsParam.position = 1
|
argsParam.position = 1
|
||||||
var objType = createObj(owner, n.info)
|
var objType = createObj(owner, n.info)
|
||||||
|
incl(objType.flags, tfFinal)
|
||||||
let castExpr = createCastExpr(argsParam, objType)
|
let castExpr = createCastExpr(argsParam, objType)
|
||||||
|
|
||||||
var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info)
|
var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info)
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ type
|
||||||
init: seq[int] # list of initialized variables
|
init: seq[int] # list of initialized variables
|
||||||
guards: TModel # nested guards
|
guards: TModel # nested guards
|
||||||
locked: seq[PNode] # locked locations
|
locked: seq[PNode] # locked locations
|
||||||
gcUnsafe: bool
|
gcUnsafe, isRecursive: bool
|
||||||
PEffects = var TEffects
|
PEffects = var TEffects
|
||||||
|
|
||||||
proc isLocalVar(a: PEffects, s: PSym): bool =
|
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
|
# are indistinguishable from normal procs (both have tyProc type) and
|
||||||
# we can detect them only by checking for attached nkEffectList.
|
# 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 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))
|
message(n.info, warnGcUnsafe, renderTree(n))
|
||||||
tracked.gcUnsafe = true
|
tracked.gcUnsafe = true
|
||||||
var effectList = op.n.sons[0]
|
var effectList = op.n.sons[0]
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,9 @@ proc sumGeneric(t: PType): int =
|
||||||
result = ord(t.kind == tyGenericInvokation)
|
result = ord(t.kind == tyGenericInvokation)
|
||||||
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||||
break
|
break
|
||||||
|
of tyProc:
|
||||||
|
# proc matche proc better than 'stmt' to disambiguate 'spawn'
|
||||||
|
return 1
|
||||||
of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
|
of tyGenericParam, tyExpr, tyStatic, tyStmt, tyTypeDesc: break
|
||||||
else: return 0
|
else: return 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -342,9 +342,10 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
||||||
result = t.id == startId
|
result = t.id == startId
|
||||||
# Inheritance can introduce cyclic types, however this is not relevant
|
# Inheritance can introduce cyclic types, however this is not relevant
|
||||||
# as the type that is passed to 'new' is statically known!
|
# as the type that is passed to 'new' is statically known!
|
||||||
#if t.kind == tyObject and tfFinal notin t.flags:
|
# er but we use it also for the write barrier ...
|
||||||
# # damn inheritance may introduce cycles:
|
if t.kind == tyObject and tfFinal notin t.flags:
|
||||||
# result = true
|
# damn inheritance may introduce cycles:
|
||||||
|
result = true
|
||||||
of tyProc: result = typ.callConv == ccClosure
|
of tyProc: result = typ.callConv == ccClosure
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2018,7 +2018,7 @@ when not defined(sysFatal):
|
||||||
e.msg = message & arg
|
e.msg = message & arg
|
||||||
raise e
|
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
|
## get type information for `x`. Ordinary code should not use this, but
|
||||||
## the `typeinfo` module instead.
|
## 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``
|
## Returns ``false`` if the end of the file has been reached, ``true``
|
||||||
## otherwise. If ``false`` is returned `line` contains no new data.
|
## otherwise. If ``false`` is returned `line` contains no new data.
|
||||||
|
|
||||||
|
when not defined(booting):
|
||||||
proc writeln*[Ty](f: TFile, x: varargs[Ty, `$`]) {.inline,
|
proc writeln*[Ty](f: TFile, x: varargs[Ty, `$`]) {.inline,
|
||||||
tags: [FWriteIO].}
|
tags: [FWriteIO], gcsafe.}
|
||||||
## writes the values `x` to `f` and then writes "\n".
|
## writes the values `x` to `f` and then writes "\n".
|
||||||
## May throw an IO exception.
|
## 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.}
|
proc getFileSize*(f: TFile): int64 {.tags: [FReadIO], gcsafe.}
|
||||||
## retrieves the file size (in bytes) of `f`.
|
## retrieves the file size (in bytes) of `f`.
|
||||||
|
|
@ -2935,3 +2939,6 @@ when not defined(booting):
|
||||||
|
|
||||||
template isStatic*(x): expr = compiles(static(x))
|
template isStatic*(x): expr = compiles(static(x))
|
||||||
# checks whether `x` is a value known at compile-time
|
# checks whether `x` is a value known at compile-time
|
||||||
|
|
||||||
|
when hasThreadSupport:
|
||||||
|
when hostOS != "standalone": include "system/sysspawn"
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@
|
||||||
# distribution, for details about the copyright.
|
# 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, mt: PNimType, shallow: bool) {.gcsafe.}
|
||||||
proc genericAssignAux(dest, src: pointer, n: ptr TNimNode, shallow: bool) =
|
proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
|
||||||
|
shallow: bool) {.gcsafe.} =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[TAddress](dest)
|
||||||
s = cast[TAddress](src)
|
s = cast[TAddress](src)
|
||||||
|
|
@ -139,8 +140,8 @@ proc genericAssignOpenArray(dest, src: pointer, len: int,
|
||||||
genericAssign(cast[pointer](d +% i*% mt.base.size),
|
genericAssign(cast[pointer](d +% i*% mt.base.size),
|
||||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
cast[pointer](s +% i*% mt.base.size), mt.base)
|
||||||
|
|
||||||
proc objectInit(dest: pointer, typ: PNimType) {.compilerProc.}
|
proc objectInit(dest: pointer, typ: PNimType) {.compilerProc, gcsafe.}
|
||||||
proc objectInitAux(dest: pointer, n: ptr TNimNode) =
|
proc objectInitAux(dest: pointer, n: ptr TNimNode) {.gcsafe.} =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[TAddress](dest)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkNone: sysAssert(false, "objectInitAux")
|
of nkNone: sysAssert(false, "objectInitAux")
|
||||||
|
|
@ -184,7 +185,7 @@ else:
|
||||||
mixin destroy
|
mixin destroy
|
||||||
for i in countup(0, r.len - 1): destroy(r[i])
|
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) =
|
proc genericResetAux(dest: pointer, n: ptr TNimNode) =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[TAddress](dest)
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2014 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -49,9 +49,9 @@ proc deinitRawChannel(p: pointer) =
|
||||||
deinitSysCond(c.cond)
|
deinitSysCond(c.cond)
|
||||||
|
|
||||||
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||||
mode: TLoadStoreMode)
|
mode: TLoadStoreMode) {.gcsafe.}
|
||||||
proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
||||||
mode: TLoadStoreMode) =
|
mode: TLoadStoreMode) {.gcsafe.} =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[TAddress](dest)
|
||||||
s = cast[TAddress](src)
|
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) =
|
proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
||||||
# to save space, the generic is as small as possible
|
# to save space, the generic is as small as possible
|
||||||
acquireSys(q.lock)
|
|
||||||
q.ready = true
|
q.ready = true
|
||||||
while q.count <= 0:
|
while q.count <= 0:
|
||||||
waitSysCond(q.cond, q.lock)
|
waitSysCond(q.cond, q.lock)
|
||||||
|
|
@ -218,17 +217,29 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
||||||
releaseSys(q.lock)
|
releaseSys(q.lock)
|
||||||
sysFatal(EInvalidValue, "cannot receive message of wrong type")
|
sysFatal(EInvalidValue, "cannot receive message of wrong type")
|
||||||
rawRecv(q, res, typ)
|
rawRecv(q, res, typ)
|
||||||
releaseSys(q.lock)
|
|
||||||
|
|
||||||
proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
|
proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
|
||||||
## receives a message from the channel `c`. This blocks until
|
## receives a message from the channel `c`. This blocks until
|
||||||
## a message has arrived! You may use ``peek`` to avoid the blocking.
|
## a message has arrived! You may use ``peek`` to avoid the blocking.
|
||||||
var q = cast[PRawChannel](addr(c))
|
var q = cast[PRawChannel](addr(c))
|
||||||
|
acquireSys(q.lock)
|
||||||
llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))
|
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 =
|
proc peek*[TMsg](c: var TChannel[TMsg]): int =
|
||||||
## returns the current number of messages in the channel `c`. Returns -1
|
## 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))
|
var q = cast[PRawChannel](addr(c))
|
||||||
if q.mask != ChannelDeadMask:
|
if q.mask != ChannelDeadMask:
|
||||||
lockChannel(q):
|
lockChannel(q):
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# The generic ``repr`` procedure. It is an invaluable debugging tool.
|
# The generic ``repr`` procedure. It is an invaluable debugging tool.
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
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 reprInt(x: int64): string {.compilerproc.} = return $x
|
||||||
proc reprFloat(x: float): 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
|
type
|
||||||
PByteArray = ptr array[0.. 0xffff, int8]
|
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
|
case typ.kind
|
||||||
of tyEnum: add result, reprEnum(elem, typ)
|
of tyEnum: add result, reprEnum(elem, typ)
|
||||||
of tyBool: add result, reprBool(bool(elem))
|
of tyBool: add result, reprBool(bool(elem))
|
||||||
|
|
@ -147,7 +147,7 @@ when not defined(useNimRtl):
|
||||||
for i in 0..cl.indent-1: add result, ' '
|
for i in 0..cl.indent-1: add result, ' '
|
||||||
|
|
||||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
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,
|
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||||
cl: var TReprClosure) =
|
cl: var TReprClosure) =
|
||||||
|
|
@ -172,7 +172,7 @@ when not defined(useNimRtl):
|
||||||
add result, "]"
|
add result, "]"
|
||||||
|
|
||||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||||
cl: var TReprClosure) =
|
cl: var TReprClosure) {.gcsafe.} =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkNone: sysAssert(false, "reprRecordAux")
|
of nkNone: sysAssert(false, "reprRecordAux")
|
||||||
of nkSlot:
|
of nkSlot:
|
||||||
|
|
|
||||||
|
|
@ -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.}
|
{.push stackTrace:off.}
|
||||||
include system.syslocks
|
|
||||||
|
|
||||||
when (defined(x86) or defined(amd64)) and defined(gcc):
|
when (defined(x86) or defined(amd64)) and defined(gcc):
|
||||||
proc cpuRelax {.inline.} =
|
proc cpuRelax {.inline.} =
|
||||||
|
|
@ -10,12 +21,12 @@ elif (defined(x86) or defined(amd64)) and defined(vcc):
|
||||||
proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
|
proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
|
||||||
elif defined(intelc):
|
elif defined(intelc):
|
||||||
proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
|
proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
|
||||||
else:
|
elif false:
|
||||||
from os import sleep
|
from os import sleep
|
||||||
|
|
||||||
proc cpuRelax {.inline.} = os.sleep(1)
|
proc cpuRelax {.inline.} = os.sleep(1)
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows) and not defined(gcc):
|
||||||
proc interlockedCompareExchange(p: pointer; exchange, comparand: int32): int32
|
proc interlockedCompareExchange(p: pointer; exchange, comparand: int32): int32
|
||||||
{.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.}
|
{.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.}
|
||||||
|
|
||||||
|
|
@ -70,6 +81,7 @@ proc await(cv: var FastCondVar) =
|
||||||
# return
|
# return
|
||||||
# cpuRelax()
|
# cpuRelax()
|
||||||
#cv.slowPath = true
|
#cv.slowPath = true
|
||||||
|
# XXX For some reason this crashes some test programs
|
||||||
await(cv.slow)
|
await(cv.slow)
|
||||||
cv.event = false
|
cv.event = false
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue