forward type alignment information to seqs (#12430)
This commit is contained in:
parent
a8f030fea2
commit
4005f0d0e4
25 changed files with 152 additions and 114 deletions
|
|
@ -1301,9 +1301,10 @@ proc genNewSeq(p: BProc, e: PNode) =
|
||||||
initLocExpr(p, e[2], b)
|
initLocExpr(p, e[2], b)
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
let seqtype = skipTypes(e[1].typ, abstractVarRange)
|
let seqtype = skipTypes(e[1].typ, abstractVarRange)
|
||||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
|
||||||
[a.rdLoc, b.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
|
[a.rdLoc, b.rdLoc,
|
||||||
getSeqPayloadType(p.module, seqtype)])
|
getTypeDesc(p.module, seqtype.lastSon),
|
||||||
|
getSeqPayloadType(p.module, seqtype)])
|
||||||
else:
|
else:
|
||||||
let lenIsZero = optNilSeqs notin p.options and
|
let lenIsZero = optNilSeqs notin p.options and
|
||||||
e[2].kind == nkIntLit and e[2].intVal == 0
|
e[2].kind == nkIntLit and e[2].intVal == 0
|
||||||
|
|
@ -1316,9 +1317,10 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||||
initLocExpr(p, e[1], a)
|
initLocExpr(p, e[1], a)
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false)
|
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false)
|
||||||
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
|
||||||
[d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
|
[d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
|
||||||
getSeqPayloadType(p.module, seqtype)])
|
getSeqPayloadType(p.module, seqtype),
|
||||||
|
])
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e, ropecg(p.module,
|
putIntoDest(p, d, e, ropecg(p.module,
|
||||||
"($1)#nimNewSeqOfCap($2, $3)", [
|
"($1)#nimNewSeqOfCap($2, $3)", [
|
||||||
|
|
@ -1425,7 +1427,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
let l = intLiteral(n.len)
|
let l = intLiteral(n.len)
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
let seqtype = n.typ
|
let seqtype = n.typ
|
||||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
|
||||||
[rdLoc dest[], l, getTypeDesc(p.module, seqtype.lastSon),
|
[rdLoc dest[], l, getTypeDesc(p.module, seqtype.lastSon),
|
||||||
getSeqPayloadType(p.module, seqtype)])
|
getSeqPayloadType(p.module, seqtype)])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1456,7 +1458,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||||
let L = toInt(lengthOrd(p.config, n[1].typ))
|
let L = toInt(lengthOrd(p.config, n[1].typ))
|
||||||
if optSeqDestructors in p.config.globalOptions:
|
if optSeqDestructors in p.config.globalOptions:
|
||||||
let seqtype = n.typ
|
let seqtype = n.typ
|
||||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
|
||||||
[rdLoc d, L, getTypeDesc(p.module, seqtype.lastSon),
|
[rdLoc d, L, getTypeDesc(p.module, seqtype.lastSon),
|
||||||
getSeqPayloadType(p.module, seqtype)])
|
getSeqPayloadType(p.module, seqtype)])
|
||||||
else:
|
else:
|
||||||
|
|
@ -2224,9 +2226,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
|
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
|
||||||
of mAlignOf:
|
of mAlignOf:
|
||||||
let t = e[1].typ.skipTypes({tyTypeDesc})
|
let t = e[1].typ.skipTypes({tyTypeDesc})
|
||||||
if not p.module.compileToCpp:
|
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t)])
|
||||||
p.module.includeHeader("<stdalign.h>")
|
|
||||||
putIntoDest(p, d, e, "((NI)alignof($1))" % [getTypeDesc(p.module, t)])
|
|
||||||
of mOffsetOf:
|
of mOffsetOf:
|
||||||
var dotExpr: PNode
|
var dotExpr: PNode
|
||||||
block findDotExpr:
|
block findDotExpr:
|
||||||
|
|
|
||||||
|
|
@ -999,11 +999,14 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||||
let nameHcr = tiNameForHcr(m, name)
|
let nameHcr = tiNameForHcr(m, name)
|
||||||
|
|
||||||
var size: Rope
|
var size: Rope
|
||||||
if tfIncompleteStruct in typ.flags: size = rope"void*"
|
if tfIncompleteStruct in typ.flags:
|
||||||
else: size = getTypeDesc(m, origType)
|
size = rope"void*"
|
||||||
|
else:
|
||||||
|
size = getTypeDesc(m, origType)
|
||||||
m.s[cfsTypeInit3].addf(
|
m.s[cfsTypeInit3].addf(
|
||||||
"$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n",
|
"$1.size = sizeof($2);$n$1.align = NIM_ALIGNOF($2);$n$1.kind = $3;$n$1.base = $4;$n",
|
||||||
[nameHcr, size, rope(nimtypeKind), base])
|
[nameHcr, size, rope(nimtypeKind), base]
|
||||||
|
)
|
||||||
# compute type flags for GC optimization
|
# compute type flags for GC optimization
|
||||||
var flags = 0
|
var flags = 0
|
||||||
if not containsGarbageCollectedRef(typ): flags = flags or 1
|
if not containsGarbageCollectedRef(typ): flags = flags or 1
|
||||||
|
|
@ -1313,10 +1316,7 @@ proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo)
|
||||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
let traceImpl = genHook(m, t, info, attachedTrace)
|
||||||
let disposeImpl = genHook(m, t, info, attachedDispose)
|
let disposeImpl = genHook(m, t, info, attachedDispose)
|
||||||
|
|
||||||
m.s[cfsTypeInit3].addf("$1.destructor = (void*)$2; $1.size = sizeof($3);$n" &
|
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6;", [
|
||||||
"$1.name = $4;$n" &
|
|
||||||
"$1.traceImpl = (void*)$5;$n" &
|
|
||||||
"$1.disposeImpl = (void*)$6;$n", [
|
|
||||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
name, destroyImpl, getTypeDesc(m, t), typeName,
|
||||||
traceImpl, disposeImpl])
|
traceImpl, disposeImpl])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ proc initDefines*(symbols: StringTableRef) =
|
||||||
defineSymbol("nimnomagic64")
|
defineSymbol("nimnomagic64")
|
||||||
defineSymbol("nimNewShiftOps")
|
defineSymbol("nimNewShiftOps")
|
||||||
defineSymbol("nimHasCursor")
|
defineSymbol("nimHasCursor")
|
||||||
|
defineSymbol("nimAlignPragma")
|
||||||
defineSymbol("nimHasExceptionsQuery")
|
defineSymbol("nimHasExceptionsQuery")
|
||||||
defineSymbol("nimHasIsNamedTuple")
|
defineSymbol("nimHasIsNamedTuple")
|
||||||
defineSymbol("nimHashOrdinalFixed")
|
defineSymbol("nimHashOrdinalFixed")
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ else:
|
||||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
||||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
||||||
importCompilerProc.}
|
importCompilerProc.}
|
||||||
proc incrSeq(seq: PGenSeq, elemSize: int): PGenSeq {.importCompilerProc.}
|
proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc.}
|
||||||
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
|
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
|
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
|
||||||
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
|
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
|
||||||
|
|
@ -180,7 +180,7 @@ proc extendSeq*(x: Any) =
|
||||||
## performs ``setLen(x, x.len+1)``. `x` needs to represent a ``seq``.
|
## performs ``setLen(x, x.len+1)``. `x` needs to represent a ``seq``.
|
||||||
assert x.rawType.kind == tySequence
|
assert x.rawType.kind == tySequence
|
||||||
var y = cast[ptr PGenSeq](x.value)[]
|
var y = cast[ptr PGenSeq](x.value)[]
|
||||||
var z = incrSeq(y, x.rawType.base.size)
|
var z = incrSeq(y, x.rawType.base.size, x.rawType.base.align)
|
||||||
# 'incrSeq' already freed the memory for us and copied over the RC!
|
# 'incrSeq' already freed the memory for us and copied over the RC!
|
||||||
# So we simply copy the raw pointer into 'x.value':
|
# So we simply copy the raw pointer into 'x.value':
|
||||||
cast[ppointer](x.value)[] = z
|
cast[ppointer](x.value)[] = z
|
||||||
|
|
@ -195,6 +195,9 @@ proc skipRange(x: PNimType): PNimType {.inline.} =
|
||||||
result = x
|
result = x
|
||||||
if result.kind == tyRange: result = result.base
|
if result.kind == tyRange: result = result.base
|
||||||
|
|
||||||
|
proc align(address, alignment: int): int =
|
||||||
|
result = (address + (alignment - 1)) and not (alignment - 1)
|
||||||
|
|
||||||
proc `[]`*(x: Any, i: int): Any =
|
proc `[]`*(x: Any, i: int): Any =
|
||||||
## accessor for an any `x` that represents an array or a sequence.
|
## accessor for an any `x` that represents an array or a sequence.
|
||||||
case x.rawType.kind
|
case x.rawType.kind
|
||||||
|
|
@ -209,7 +212,7 @@ proc `[]`*(x: Any, i: int): Any =
|
||||||
var bs = x.rawType.base.size
|
var bs = x.rawType.base.size
|
||||||
if i >=% cast[PGenSeq](s).len:
|
if i >=% cast[PGenSeq](s).len:
|
||||||
raise newException(IndexError, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
raise newException(IndexError, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
||||||
return newAny(s +!! (GenericSeqSize+i*bs), x.rawType.base)
|
return newAny(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), x.rawType.base)
|
||||||
else: assert false
|
else: assert false
|
||||||
|
|
||||||
proc `[]=`*(x: Any, i: int, y: Any) =
|
proc `[]=`*(x: Any, i: int, y: Any) =
|
||||||
|
|
@ -228,7 +231,7 @@ proc `[]=`*(x: Any, i: int, y: Any) =
|
||||||
if i >=% cast[PGenSeq](s).len:
|
if i >=% cast[PGenSeq](s).len:
|
||||||
raise newException(IndexError, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
raise newException(IndexError, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
|
||||||
assert y.rawType == x.rawType.base
|
assert y.rawType == x.rawType.base
|
||||||
genericAssign(s +!! (GenericSeqSize+i*bs), y.value, y.rawType)
|
genericAssign(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), y.value, y.rawType)
|
||||||
else: assert false
|
else: assert false
|
||||||
|
|
||||||
proc len*(x: Any): int =
|
proc len*(x: Any): int =
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,6 @@ typedef char* NCSTRING;
|
||||||
#define ALLOC_0(size) calloc(1, size)
|
#define ALLOC_0(size) calloc(1, size)
|
||||||
#define DL_ALLOC_0(size) dlcalloc(1, size)
|
#define DL_ALLOC_0(size) dlcalloc(1, size)
|
||||||
|
|
||||||
#define GenericSeqSize sizeof(TGenericSeq)
|
|
||||||
#define paramCount() cmdCount
|
#define paramCount() cmdCount
|
||||||
|
|
||||||
// NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0
|
// NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0
|
||||||
|
|
@ -546,8 +545,10 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, ""
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# define NIM_ALIGN(x) __declspec(align(x))
|
# define NIM_ALIGN(x) __declspec(align(x))
|
||||||
|
# define NIM_ALIGNOF(x) __alignof(x)
|
||||||
#else
|
#else
|
||||||
# define NIM_ALIGN(x) __attribute__((aligned(x)))
|
# define NIM_ALIGN(x) __attribute__((aligned(x)))
|
||||||
|
# define NIM_ALIGNOF(x) __alignof__(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------------- platform specific includes ----------------------- */
|
/* ---------------- platform specific includes ----------------------- */
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,7 @@ else:
|
||||||
when useNSGetEnviron:
|
when useNSGetEnviron:
|
||||||
var gEnv = NSGetEnviron()[]
|
var gEnv = NSGetEnviron()[]
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while gEnv[i] != nil:
|
||||||
if gEnv[i] == nil: break
|
|
||||||
add environment, $gEnv[i]
|
add environment, $gEnv[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
envComputed = true
|
envComputed = true
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,7 @@ when not defined(js) and not defined(nimSeqsV2):
|
||||||
len, reserved: int
|
len, reserved: int
|
||||||
when defined(gogc):
|
when defined(gogc):
|
||||||
elemSize: int
|
elemSize: int
|
||||||
|
elemAlign: int
|
||||||
PGenericSeq {.exportc.} = ptr TGenericSeq
|
PGenericSeq {.exportc.} = ptr TGenericSeq
|
||||||
# len and space without counting the terminating zero:
|
# len and space without counting the terminating zero:
|
||||||
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
|
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
|
||||||
|
|
@ -1123,6 +1124,13 @@ elif hostOS != "standalone":
|
||||||
var programResult* {.compilerproc, exportc: "nim_program_result".}: int
|
var programResult* {.compilerproc, exportc: "nim_program_result".}: int
|
||||||
## deprecated, prefer ``quit``
|
## deprecated, prefer ``quit``
|
||||||
|
|
||||||
|
proc align(address, alignment: int): int =
|
||||||
|
if alignment == 0: # Actually, this is illegal. This branch exists to actively
|
||||||
|
# hide problems.
|
||||||
|
result = address
|
||||||
|
else:
|
||||||
|
result = (address + (alignment - 1)) and not (alignment - 1)
|
||||||
|
|
||||||
when defined(nimdoc):
|
when defined(nimdoc):
|
||||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||||
## Stops the program immediately with an exit code.
|
## Stops the program immediately with an exit code.
|
||||||
|
|
@ -1698,6 +1706,7 @@ when not defined(js) and defined(nimV2):
|
||||||
TNimType {.compilerproc.} = object
|
TNimType {.compilerproc.} = object
|
||||||
destructor: pointer
|
destructor: pointer
|
||||||
size: int
|
size: int
|
||||||
|
align: int
|
||||||
name: cstring
|
name: cstring
|
||||||
traceImpl: pointer
|
traceImpl: pointer
|
||||||
disposeImpl: pointer
|
disposeImpl: pointer
|
||||||
|
|
@ -1709,7 +1718,6 @@ when notJSnotNims and defined(nimSeqsV2):
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
|
|
||||||
when notJSnotNims:
|
when notJSnotNims:
|
||||||
proc writeStackTrace*() {.tags: [], gcsafe, raises: [].}
|
proc writeStackTrace*() {.tags: [], gcsafe, raises: [].}
|
||||||
## Writes the current stack trace to ``stderr``. This is only works
|
## Writes the current stack trace to ``stderr``. This is only works
|
||||||
|
|
@ -1988,8 +1996,8 @@ proc abs*(x: int64): int64 {.magic: "AbsI", noSideEffect.} =
|
||||||
result = if x < 0: -x else: x
|
result = if x < 0: -x else: x
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
|
|
||||||
when not defined(js):
|
when not defined(js):
|
||||||
|
|
||||||
proc likelyProc(val: bool): bool {.importc: "NIM_LIKELY", nodecl, noSideEffect.}
|
proc likelyProc(val: bool): bool {.importc: "NIM_LIKELY", nodecl, noSideEffect.}
|
||||||
proc unlikelyProc(val: bool): bool {.importc: "NIM_UNLIKELY", nodecl, noSideEffect.}
|
proc unlikelyProc(val: bool): bool {.importc: "NIM_UNLIKELY", nodecl, noSideEffect.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ type
|
||||||
data: TrunkBuckets
|
data: TrunkBuckets
|
||||||
|
|
||||||
type
|
type
|
||||||
AlignType = BiggestFloat
|
|
||||||
FreeCell {.final, pure.} = object
|
FreeCell {.final, pure.} = object
|
||||||
next: ptr FreeCell # next free cell in chunk (overlaid with refcount)
|
next: ptr FreeCell # next free cell in chunk (overlaid with refcount)
|
||||||
when not defined(gcDestructors):
|
when not defined(gcDestructors):
|
||||||
|
|
@ -68,16 +67,20 @@ type
|
||||||
freeList: ptr FreeCell
|
freeList: ptr FreeCell
|
||||||
free: int # how many bytes remain
|
free: int # how many bytes remain
|
||||||
acc: int # accumulator for small object allocation
|
acc: int # accumulator for small object allocation
|
||||||
when defined(cpu32):
|
when defined(nimAlignPragma):
|
||||||
align: int
|
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||||
data: AlignType # start of usable memory
|
else:
|
||||||
|
data: UncheckedArray[byte]
|
||||||
|
|
||||||
BigChunk = object of BaseChunk # not necessarily > PageSize!
|
BigChunk = object of BaseChunk # not necessarily > PageSize!
|
||||||
next, prev: PBigChunk # chunks of the same (or bigger) size
|
next, prev: PBigChunk # chunks of the same (or bigger) size
|
||||||
data: AlignType # start of usable memory
|
when defined(nimAlignPragma):
|
||||||
|
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||||
|
else:
|
||||||
|
data: UncheckedArray[byte]
|
||||||
|
|
||||||
template smallChunkOverhead(): untyped = sizeof(SmallChunk)-sizeof(AlignType)
|
template smallChunkOverhead(): untyped = sizeof(SmallChunk)
|
||||||
template bigChunkOverhead(): untyped = sizeof(BigChunk)-sizeof(AlignType)
|
template bigChunkOverhead(): untyped = sizeof(BigChunk)
|
||||||
|
|
||||||
# ------------- chunk table ---------------------------------------------------
|
# ------------- chunk table ---------------------------------------------------
|
||||||
# We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk
|
# We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk
|
||||||
|
|
|
||||||
|
|
@ -66,17 +66,16 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
cast[PGenericSeq](ss).len = seq.len
|
cast[PGenericSeq](ss).len = seq.len
|
||||||
unsureAsgnRef(x, ss)
|
unsureAsgnRef(x, ss)
|
||||||
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||||
copyMem(cast[pointer](dst +% GenericSeqSize),
|
copyMem(cast[pointer](dst +% align(GenericSeqSize, mt.base.align)),
|
||||||
cast[pointer](cast[ByteAddress](s2) +% GenericSeqSize),
|
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align)),
|
||||||
seq.len * mt.base.size)
|
seq.len *% mt.base.size)
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, newSeq(mt, seq.len))
|
unsureAsgnRef(x, newSeq(mt, seq.len))
|
||||||
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
genericAssignAux(
|
genericAssignAux(
|
||||||
cast[pointer](dst +% i *% mt.base.size +% GenericSeqSize),
|
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
|
||||||
cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
|
||||||
GenericSeqSize),
|
|
||||||
mt.base, shallow)
|
mt.base, shallow)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
var it = mt.base
|
var it = mt.base
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ when not usesDestructors:
|
||||||
x[] = nil
|
x[] = nil
|
||||||
else:
|
else:
|
||||||
var ss = cast[NimString](s2)
|
var ss = cast[NimString](s2)
|
||||||
var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize))
|
var ns = cast[NimString](alloc(t.region, GenericSeqSize + ss.len+1))
|
||||||
copyMem(ns, ss, ss.len+1 + GenericSeqSize)
|
copyMem(ns, ss, ss.len+1 + GenericSeqSize)
|
||||||
x[] = ns
|
x[] = ns
|
||||||
else:
|
else:
|
||||||
|
|
@ -239,7 +239,7 @@ when not usesDestructors:
|
||||||
else:
|
else:
|
||||||
sysAssert(dest != nil, "dest == nil")
|
sysAssert(dest != nil, "dest == nil")
|
||||||
if mode == mStore:
|
if mode == mStore:
|
||||||
x[] = alloc0(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
x[] = alloc0(t.region, align(GenericSeqSize, mt.base.align) +% seq.len *% mt.base.size)
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, newSeq(mt, seq.len))
|
unsureAsgnRef(x, newSeq(mt, seq.len))
|
||||||
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||||
|
|
@ -248,9 +248,9 @@ when not usesDestructors:
|
||||||
dstseq.reserved = seq.len
|
dstseq.reserved = seq.len
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
storeAux(
|
storeAux(
|
||||||
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i*% mt.base.size),
|
||||||
cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +%
|
||||||
GenericSeqSize),
|
i *% mt.base.size),
|
||||||
mt.base, t, mode)
|
mt.base, t, mode)
|
||||||
if mode != mStore: dealloc(t.region, s2)
|
if mode != mStore: dealloc(t.region, s2)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
|
|
@ -452,4 +452,3 @@ proc ready*[TMsg](c: var Channel[TMsg]): bool =
|
||||||
## new messages.
|
## new messages.
|
||||||
var q = cast[PRawChannel](addr(c))
|
var q = cast[PRawChannel](addr(c))
|
||||||
result = q.ready
|
result = q.ready
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,8 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
genericDeepCopyAux(
|
genericDeepCopyAux(
|
||||||
cast[pointer](dst +% i *% mt.base.size +% GenericSeqSize),
|
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
|
||||||
cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
|
||||||
GenericSeqSize),
|
|
||||||
mt.base, tab)
|
mt.base, tab)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
# we need to copy m_type field for tyObject, as it could be empty for
|
# we need to copy m_type field for tyObject, as it could be empty for
|
||||||
|
|
|
||||||
|
|
@ -339,8 +339,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
|
||||||
var s = cast[PGenericSeq](d)
|
var s = cast[PGenericSeq](d)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
forAllChildrenAux(cast[pointer](d +% align(GenericSeqSize, cell.typ.base.align) +% i *% cell.typ.base.size), cell.typ.base, op)
|
||||||
GenericSeqSize), cell.typ.base, op)
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc addNewObjToZCT(res: PCell, gch: var GcHeap) {.inline.} =
|
proc addNewObjToZCT(res: PCell, gch: var GcHeap) {.inline.} =
|
||||||
|
|
@ -444,7 +443,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
# `newObj` already uses locks, so no need for them here.
|
# `newObj` already uses locks, so no need for them here.
|
||||||
let size = len * typ.base.size + GenericSeqSize
|
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
|
|
@ -480,7 +479,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
|
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
let size = len * typ.base.size + GenericSeqSize
|
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||||
result = newObjRC1(typ, size)
|
result = newObjRC1(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
|
|
@ -495,11 +494,13 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
|
||||||
sysAssert(allocInv(gch.region), "growObj begin")
|
sysAssert(allocInv(gch.region), "growObj begin")
|
||||||
|
|
||||||
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
||||||
var elemSize = 1
|
var elemSize,elemAlign = 1
|
||||||
if ol.typ.kind != tyString: elemSize = ol.typ.base.size
|
if ol.typ.kind != tyString:
|
||||||
|
elemSize = ol.typ.base.size
|
||||||
|
elemAlign = ol.typ.base.align
|
||||||
incTypeSize ol.typ, newsize
|
incTypeSize ol.typ, newsize
|
||||||
|
|
||||||
var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len * elemSize
|
||||||
copyMem(res, ol, oldsize + sizeof(Cell))
|
copyMem(res, ol, oldsize + sizeof(Cell))
|
||||||
zeroMem(cast[pointer](cast[ByteAddress](res) +% oldsize +% sizeof(Cell)),
|
zeroMem(cast[pointer](cast[ByteAddress](res) +% oldsize +% sizeof(Cell)),
|
||||||
newsize-oldsize)
|
newsize-oldsize)
|
||||||
|
|
|
||||||
|
|
@ -291,8 +291,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
|
||||||
var s = cast[PGenericSeq](d)
|
var s = cast[PGenericSeq](d)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
forAllChildrenAux(cast[pointer](d +% align(GenericSeqSize, cell.typ.base.align) +% i *% cell.typ.base.size), cell.typ.base, op)
|
||||||
GenericSeqSize), cell.typ.base, op)
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
{.push stackTrace: off, profiler:off.}
|
{.push stackTrace: off, profiler:off.}
|
||||||
|
|
@ -359,7 +358,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
|
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
# `newObj` already uses locks, so no need for them here.
|
# `newObj` already uses locks, so no need for them here.
|
||||||
let size = addInt(mulInt(len, typ.base.size), GenericSeqSize)
|
let size = addInt(align(GenericSeqSize, typ.base.align), mulInt(len, typ.base.size))
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
|
|
@ -378,11 +377,13 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
|
||||||
gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
|
gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
|
||||||
|
|
||||||
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
||||||
var elemSize = 1
|
var elemSize, elemAlign = 1
|
||||||
if ol.typ.kind != tyString: elemSize = ol.typ.base.size
|
if ol.typ.kind != tyString:
|
||||||
|
elemSize = ol.typ.base.size
|
||||||
|
elemAlign = ol.typ.base.align
|
||||||
incTypeSize ol.typ, newsize
|
incTypeSize ol.typ, newsize
|
||||||
|
|
||||||
var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len*elemSize
|
||||||
copyMem(res, ol, oldsize + sizeof(Cell))
|
copyMem(res, ol, oldsize + sizeof(Cell))
|
||||||
zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
|
zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
|
||||||
newsize-oldsize)
|
newsize-oldsize)
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,11 @@ template decTypeSize(cell, t) =
|
||||||
when defined(nimTypeNames):
|
when defined(nimTypeNames):
|
||||||
if t.kind in {tyString, tySequence}:
|
if t.kind in {tyString, tySequence}:
|
||||||
let cap = cast[PGenericSeq](cellToUsr(cell)).space
|
let cap = cast[PGenericSeq](cellToUsr(cell)).space
|
||||||
let size = if t.kind == tyString: cap+1+GenericSeqSize
|
let size =
|
||||||
else: cap * t.base.size + GenericSeqSize
|
if t.kind == tyString:
|
||||||
|
cap + 1 + GenericSeqSize
|
||||||
|
else:
|
||||||
|
align(GenericSeqSize, t.base.align) + cap * t.base.size
|
||||||
atomicDec t.sizes, size+sizeof(Cell)
|
atomicDec t.sizes, size+sizeof(Cell)
|
||||||
else:
|
else:
|
||||||
atomicDec t.sizes, t.base.size+sizeof(Cell)
|
atomicDec t.sizes, t.base.size+sizeof(Cell)
|
||||||
|
|
|
||||||
|
|
@ -259,8 +259,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
|
||||||
var s = cast[PGenericSeq](d)
|
var s = cast[PGenericSeq](d)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
forAllChildrenAux(cast[pointer](d +% align(GenericSeqSize, cell.typ.base.align) +% i *% cell.typ.base.size), cell.typ.base, op)
|
||||||
GenericSeqSize), cell.typ.base, op)
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
|
proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
|
||||||
|
|
@ -308,14 +307,14 @@ when not defined(nimSeqsV2):
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
# `newObj` already uses locks, so no need for them here.
|
# `newObj` already uses locks, so no need for them here.
|
||||||
let size = len * typ.base.size + GenericSeqSize
|
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
when defined(memProfiler): nimProfile(size)
|
when defined(memProfiler): nimProfile(size)
|
||||||
|
|
||||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
let size = len * typ.base.size + GenericSeqSize
|
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||||
result = newObj(typ, size)
|
result = newObj(typ, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
|
|
@ -329,11 +328,13 @@ when not defined(nimSeqsV2):
|
||||||
gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
|
gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
|
||||||
|
|
||||||
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
|
||||||
var elemSize = 1
|
var elemSize, elemAlign = 1
|
||||||
if ol.typ.kind != tyString: elemSize = ol.typ.base.size
|
if ol.typ.kind != tyString:
|
||||||
|
elemSize = ol.typ.base.size
|
||||||
|
elemAlign = ol.typ.base.align
|
||||||
incTypeSize ol.typ, newsize
|
incTypeSize ol.typ, newsize
|
||||||
|
|
||||||
var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len*elemSize
|
||||||
copyMem(res, ol, oldsize + sizeof(Cell))
|
copyMem(res, ol, oldsize + sizeof(Cell))
|
||||||
zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
|
zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
|
||||||
newsize-oldsize)
|
newsize-oldsize)
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
|
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
let size = roundup(len * typ.base.size + GenericSeqSize, MemAlign)
|
let size = roundup(align(GenericSeqSize, typ.base.align) + len * typ.base.size, MemAlign)
|
||||||
result = rawNewSeq(tlRegion, typ, size)
|
result = rawNewSeq(tlRegion, typ, size)
|
||||||
zeroMem(result, size)
|
zeroMem(result, size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
|
|
@ -348,7 +348,8 @@ proc growObj(regionUnused: var MemRegion; old: pointer, newsize: int): pointer =
|
||||||
result = rawNewSeq(sh.region[], typ,
|
result = rawNewSeq(sh.region[], typ,
|
||||||
roundup(newsize, MemAlign))
|
roundup(newsize, MemAlign))
|
||||||
let elemSize = if typ.kind == tyString: 1 else: typ.base.size
|
let elemSize = if typ.kind == tyString: 1 else: typ.base.size
|
||||||
let oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
let elemAlign = if typ.kind == tyString: 1 else: typ.base.align
|
||||||
|
let oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len*elemSize
|
||||||
zeroMem(result +! oldsize, newsize-oldsize)
|
zeroMem(result +! oldsize, newsize-oldsize)
|
||||||
copyMem(result, old, oldsize)
|
copyMem(result, old, oldsize)
|
||||||
dealloc(sh.region[], old, roundup(oldsize, MemAlign))
|
dealloc(sh.region[], old, roundup(oldsize, MemAlign))
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ type
|
||||||
when defined(gcHooks):
|
when defined(gcHooks):
|
||||||
head*: pointer
|
head*: pointer
|
||||||
size*: int
|
size*: int
|
||||||
|
align*: int
|
||||||
kind: TNimKind
|
kind: TNimKind
|
||||||
flags: set[TNimTypeFlag]
|
flags: set[TNimTypeFlag]
|
||||||
base*: ptr TNimType
|
base*: ptr TNimType
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc boehmGCinit {.importc: "GC_init", boehmGC.}
|
proc boehmGCinit {.importc: "GC_init", boehmGC.}
|
||||||
proc boehmGC_disable {.importc: "GC_disable", boehmGC.}
|
proc boehmGC_disable {.importc: "GC_disable", boehmGC.}
|
||||||
proc boehmGC_enable {.importc: "GC_enable", boehmGC.}
|
proc boehmGC_enable {.importc: "GC_enable", boehmGC.}
|
||||||
|
|
@ -96,6 +98,7 @@ proc initGC() =
|
||||||
proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl.})) =
|
proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl.})) =
|
||||||
typedFinalizer(obj)
|
typedFinalizer(obj)
|
||||||
|
|
||||||
|
|
||||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||||
if ntfNoRefs in typ.flags: result = allocAtomic(size)
|
if ntfNoRefs in typ.flags: result = allocAtomic(size)
|
||||||
else: result = alloc(size)
|
else: result = alloc(size)
|
||||||
|
|
@ -103,7 +106,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||||
boehmRegisterFinalizer(result, boehmgc_finalizer, typ.finalizer, nil, nil)
|
boehmRegisterFinalizer(result, boehmgc_finalizer, typ.finalizer, nil, nil)
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||||
result = newObj(typ, len * typ.base.size + GenericSeqSize)
|
result = newObj(typ, align(GenericSeqSize, typ.base.align) + len * typ.base.size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
@ -135,4 +138,3 @@ proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
||||||
proc deallocOsPages() {.inline.} = discard
|
proc deallocOsPages() {.inline.} = discard
|
||||||
|
|
||||||
include "system/cellsets"
|
include "system/cellsets"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,28 +101,32 @@ proc newObjNoInit(typ: PNimType, size: int): pointer =
|
||||||
writebarrierptr(addr(result), newObj(typ, size))
|
writebarrierptr(addr(result), newObj(typ, size))
|
||||||
|
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||||
writebarrierptr(addr(result), newObj(typ, len * typ.base.size + GenericSeqSize))
|
writebarrierptr(addr(result), newObj(typ, align(GenericSeqSize, typ.base.align) + len * typ.base.size))
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
cast[PGenericSeq](result).elemSize = typ.base.size
|
cast[PGenericSeq](result).elemSize = typ.base.size
|
||||||
|
cast[PGenericSeq](result).elemAlign = typ.base.align
|
||||||
|
|
||||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||||
writebarrierptr(addr(result), newSeq(typ, len))
|
writebarrierptr(addr(result), newSeq(typ, len))
|
||||||
|
|
||||||
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
|
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
|
||||||
result = newObj(typ, cap * typ.base.size + GenericSeqSize)
|
result = newObj(typ, align(GenericSeqSize, typ.base.align) + cap * typ.base.size)
|
||||||
cast[PGenericSeq](result).len = 0
|
cast[PGenericSeq](result).len = 0
|
||||||
cast[PGenericSeq](result).reserved = cap
|
cast[PGenericSeq](result).reserved = cap
|
||||||
cast[PGenericSeq](result).elemSize = typ.base.size
|
cast[PGenericSeq](result).elemSize = typ.base.size
|
||||||
|
cast[PGenericSeq](result).elemAlign = typ.base.align
|
||||||
|
|
||||||
proc typedMemMove(dest: pointer, src: pointer, size: uint) {.importc: "typedmemmove", dynlib: goLib.}
|
proc typedMemMove(dest: pointer, src: pointer, size: uint) {.importc: "typedmemmove", dynlib: goLib.}
|
||||||
|
|
||||||
proc growObj(old: pointer, newsize: int): pointer =
|
proc growObj(old: pointer, newsize: int): pointer =
|
||||||
# the Go GC doesn't have a realloc
|
# the Go GC doesn't have a realloc
|
||||||
|
let old = cast[PGenericSeq](old)
|
||||||
var metadataOld = cast[PGenericSeq](old)
|
var metadataOld = cast[PGenericSeq](old)
|
||||||
if metadataOld.elemSize == 0:
|
if metadataOld.elemSize == 0:
|
||||||
metadataOld.elemSize = 1
|
metadataOld.elemSize = 1
|
||||||
let oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
|
|
||||||
|
let oldsize = align(GenericSeqSize, old.elemAlign) + old.len * old.elemSize
|
||||||
writebarrierptr(addr(result), goMalloc(newsize.uint))
|
writebarrierptr(addr(result), goMalloc(newsize.uint))
|
||||||
typedMemMove(result, old, oldsize.uint)
|
typedMemMove(result, old, oldsize.uint)
|
||||||
|
|
||||||
|
|
@ -149,4 +153,3 @@ proc alloc0(r: var MemRegion, size: int): pointer =
|
||||||
proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
|
proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
|
||||||
proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
||||||
proc deallocOsPages() {.inline.} = discard
|
proc deallocOsPages() {.inline.} = discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ proc newObjNoInit(typ: PNimType, size: int): pointer =
|
||||||
|
|
||||||
{.push overflowChecks: on.}
|
{.push overflowChecks: on.}
|
||||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||||
result = newObj(typ, len * typ.base.size + GenericSeqSize)
|
result = newObj(typ, align(GenericSeqSize, typ.align) + len * typ.base.size)
|
||||||
cast[PGenericSeq](result).len = len
|
cast[PGenericSeq](result).len = len
|
||||||
cast[PGenericSeq](result).reserved = len
|
cast[PGenericSeq](result).reserved = len
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ const
|
||||||
PageSize = 1 shl PageShift
|
PageSize = 1 shl PageShift
|
||||||
PageMask = PageSize-1
|
PageMask = PageSize-1
|
||||||
|
|
||||||
MemAlign = 8 # also minimal allocatable memory block
|
MemAlign = 16 # also minimal allocatable memory block
|
||||||
|
|
||||||
BitsPerPage = PageSize div MemAlign
|
BitsPerPage = PageSize div MemAlign
|
||||||
UnitsPerPage = BitsPerPage div (sizeof(int)*8)
|
UnitsPerPage = BitsPerPage div (sizeof(int)*8)
|
||||||
|
|
@ -108,7 +108,7 @@ when not declared(nimNewSeqOfCap) and not defined(nimSeqsV2):
|
||||||
let s = cap * typ.base.size # newStr already adds GenericSeqSize
|
let s = cap * typ.base.size # newStr already adds GenericSeqSize
|
||||||
result = newStr(typ, s, ntfNoRefs notin typ.base.flags)
|
result = newStr(typ, s, ntfNoRefs notin typ.base.flags)
|
||||||
else:
|
else:
|
||||||
let s = cap * typ.base.size + GenericSeqSize
|
let s = align(GenericSeqSize, typ.base.align) + cap * typ.base.size
|
||||||
when declared(newObjNoInit):
|
when declared(newObjNoInit):
|
||||||
result = if ntfNoRefs in typ.base.flags: newObjNoInit(typ, s) else: newObj(typ, s)
|
result = if ntfNoRefs in typ.base.flags: newObjNoInit(typ, s) else: newObj(typ, s)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ when not defined(useNimRtl):
|
||||||
|
|
||||||
template payloadPtr(x: untyped): untyped = cast[PGenericSeq](x).p
|
template payloadPtr(x: untyped): untyped = cast[PGenericSeq](x).p
|
||||||
else:
|
else:
|
||||||
const payloadOffset = GenericSeqSize
|
const payloadOffset = GenericSeqSize ## the payload offset always depends on the alignment of the member type.
|
||||||
template payloadPtr(x: untyped): untyped = x
|
template payloadPtr(x: untyped): untyped = x
|
||||||
|
|
||||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||||
|
|
@ -185,7 +185,7 @@ when not defined(useNimRtl):
|
||||||
var bs = typ.base.size
|
var bs = typ.base.size
|
||||||
for i in 0..cast[PGenericSeq](p).len-1:
|
for i in 0..cast[PGenericSeq](p).len-1:
|
||||||
if i > 0: add result, ", "
|
if i > 0: add result, ", "
|
||||||
reprAux(result, cast[pointer](cast[ByteAddress](payloadPtr(p)) + payloadOffset + i*bs),
|
reprAux(result, cast[pointer](cast[ByteAddress](payloadPtr(p)) + align(payloadOffset, typ.align) + i*bs),
|
||||||
typ.base, cl)
|
typ.base, cl)
|
||||||
add result, "]"
|
add result, "]"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,27 +31,27 @@ const nimSeqVersion {.core.} = 2
|
||||||
|
|
||||||
# XXX make code memory safe for overflows in '*'
|
# XXX make code memory safe for overflows in '*'
|
||||||
|
|
||||||
proc newSeqPayload(cap, elemSize: int): pointer {.compilerRtl, raises: [].} =
|
proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises: [].} =
|
||||||
# we have to use type erasure here as Nim does not support generic
|
# we have to use type erasure here as Nim does not support generic
|
||||||
# compilerProcs. Oh well, this will all be inlined anyway.
|
# compilerProcs. Oh well, this will all be inlined anyway.
|
||||||
if cap > 0:
|
if cap > 0:
|
||||||
var p = cast[ptr NimSeqPayloadBase](allocShared0(cap * elemSize + sizeof(NimSeqPayloadBase)))
|
var p = cast[ptr NimSeqPayloadBase](allocShared0(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize))
|
||||||
p.cap = cap
|
p.cap = cap
|
||||||
result = p
|
result = p
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize: int): pointer {.
|
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
||||||
noSideEffect, raises: [].} =
|
noSideEffect, raises: [].} =
|
||||||
{.noSideEffect.}:
|
{.noSideEffect.}:
|
||||||
template `+!`(p: pointer, s: int): pointer =
|
template `+!`(p: pointer, s: int): pointer =
|
||||||
cast[pointer](cast[int](p) +% s)
|
cast[pointer](cast[int](p) +% s)
|
||||||
|
|
||||||
const headerSize = sizeof(NimSeqPayloadBase)
|
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
|
||||||
if addlen <= 0:
|
if addlen <= 0:
|
||||||
result = p
|
result = p
|
||||||
elif p == nil:
|
elif p == nil:
|
||||||
result = newSeqPayload(len+addlen, elemSize)
|
result = newSeqPayload(len+addlen, elemSize, elemAlign)
|
||||||
else:
|
else:
|
||||||
# Note: this means we cannot support things that have internal pointers as
|
# Note: this means we cannot support things that have internal pointers as
|
||||||
# they get reallocated here. This needs to be documented clearly.
|
# they get reallocated here. This needs to be documented clearly.
|
||||||
|
|
@ -87,7 +87,7 @@ proc grow*[T](x: var seq[T]; newLen: Natural; value: T) =
|
||||||
if newLen <= oldLen: return
|
if newLen <= oldLen: return
|
||||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||||
if xu.p == nil or xu.p.cap < newLen:
|
if xu.p == nil or xu.p.cap < newLen:
|
||||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T)))
|
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
|
||||||
xu.len = newLen
|
xu.len = newLen
|
||||||
for i in oldLen .. newLen-1:
|
for i in oldLen .. newLen-1:
|
||||||
xu.p.data[i] = value
|
xu.p.data[i] = value
|
||||||
|
|
@ -102,7 +102,7 @@ proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffec
|
||||||
let oldLen = x.len
|
let oldLen = x.len
|
||||||
var xu = cast[ptr NimSeqV2[T]](addr x)
|
var xu = cast[ptr NimSeqV2[T]](addr x)
|
||||||
if xu.p == nil or xu.p.cap < oldLen+1:
|
if xu.p == nil or xu.p.cap < oldLen+1:
|
||||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T)))
|
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
|
||||||
xu.len = oldLen+1
|
xu.len = oldLen+1
|
||||||
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
# .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
|
||||||
# copyMem(). This is fine as know by construction that
|
# copyMem(). This is fine as know by construction that
|
||||||
|
|
@ -119,5 +119,5 @@ proc setLen[T](s: var seq[T], newlen: Natural) =
|
||||||
if newlen <= oldLen: return
|
if newlen <= oldLen: return
|
||||||
var xu = cast[ptr NimSeqV2[T]](addr s)
|
var xu = cast[ptr NimSeqV2[T]](addr s)
|
||||||
if xu.p == nil or xu.p.cap < newlen:
|
if xu.p == nil or xu.p.cap < newlen:
|
||||||
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T)))
|
xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
|
||||||
xu.len = newlen
|
xu.len = newlen
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
|
||||||
|
|
||||||
# ----------------- sequences ----------------------------------------------
|
# ----------------- sequences ----------------------------------------------
|
||||||
|
|
||||||
proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
|
proc incrSeq(seq: PGenericSeq, elemSize, elemAlign: int): PGenericSeq {.compilerproc.} =
|
||||||
# increments the length by one:
|
# increments the length by one:
|
||||||
# this is needed for supporting ``add``;
|
# this is needed for supporting ``add``;
|
||||||
#
|
#
|
||||||
|
|
@ -255,18 +255,16 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
|
||||||
result = seq
|
result = seq
|
||||||
if result.len >= result.space:
|
if result.len >= result.space:
|
||||||
let r = resize(result.space)
|
let r = resize(result.space)
|
||||||
result = cast[PGenericSeq](growObj(result, elemSize * r +
|
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
|
||||||
GenericSeqSize))
|
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
inc(result.len)
|
inc(result.len)
|
||||||
|
|
||||||
proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerproc.} =
|
proc incrSeqV2(seq: PGenericSeq, elemSize, elemAlign: int): PGenericSeq {.compilerproc.} =
|
||||||
# incrSeq version 2
|
# incrSeq version 2
|
||||||
result = seq
|
result = seq
|
||||||
if result.len >= result.space:
|
if result.len >= result.space:
|
||||||
let r = resize(result.space)
|
let r = resize(result.space)
|
||||||
result = cast[PGenericSeq](growObj(result, elemSize * r +
|
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
|
||||||
GenericSeqSize))
|
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
|
|
||||||
template `+!`(p: pointer, s: int): pointer =
|
template `+!`(p: pointer, s: int): pointer =
|
||||||
|
|
@ -283,21 +281,19 @@ proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} =
|
||||||
when defined(nimIncrSeqV3):
|
when defined(nimIncrSeqV3):
|
||||||
result = cast[PGenericSeq](newSeq(typ, r))
|
result = cast[PGenericSeq](newSeq(typ, r))
|
||||||
result.len = s.len
|
result.len = s.len
|
||||||
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * typ.base.size)
|
copyMem(result +! align(GenericSeqSize, typ.base.align), s +! align(GenericSeqSize, typ.base.align), s.len * typ.base.size)
|
||||||
# since we steal the content from 's', it's crucial to set s's len to 0.
|
# since we steal the content from 's', it's crucial to set s's len to 0.
|
||||||
s.len = 0
|
s.len = 0
|
||||||
else:
|
else:
|
||||||
result = cast[PGenericSeq](growObj(result, typ.base.size * r +
|
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, typ.base.align) + typ.base.size * r))
|
||||||
GenericSeqSize))
|
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
|
|
||||||
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
proc setLengthSeq(seq: PGenericSeq, elemSize, elemAlign, newLen: int): PGenericSeq {.
|
||||||
compilerRtl, inl.} =
|
compilerRtl, inl.} =
|
||||||
result = seq
|
result = seq
|
||||||
if result.space < newLen:
|
if result.space < newLen:
|
||||||
let r = max(resize(result.space), newLen)
|
let r = max(resize(result.space), newLen)
|
||||||
result = cast[PGenericSeq](growObj(result, elemSize * r +
|
result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r))
|
||||||
GenericSeqSize))
|
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
elif newLen < result.len:
|
elif newLen < result.len:
|
||||||
# we need to decref here, otherwise the GC leaks!
|
# we need to decref here, otherwise the GC leaks!
|
||||||
|
|
@ -307,8 +303,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
when false: # compileOption("gc", "v2"):
|
when false: # compileOption("gc", "v2"):
|
||||||
for i in newLen..result.len-1:
|
for i in newLen..result.len-1:
|
||||||
let len0 = gch.tempStack.len
|
let len0 = gch.tempStack.len
|
||||||
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
|
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
|
||||||
GenericSeqSize +% (i*%elemSize)),
|
|
||||||
extGetCellType(result).base, waPush)
|
extGetCellType(result).base, waPush)
|
||||||
let len1 = gch.tempStack.len
|
let len1 = gch.tempStack.len
|
||||||
for i in len0 ..< len1:
|
for i in len0 ..< len1:
|
||||||
|
|
@ -318,7 +313,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
if ntfNoRefs notin extGetCellType(result).base.flags:
|
if ntfNoRefs notin extGetCellType(result).base.flags:
|
||||||
for i in newLen..result.len-1:
|
for i in newLen..result.len-1:
|
||||||
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
|
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
|
||||||
GenericSeqSize +% (i*%elemSize)),
|
align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
|
||||||
extGetCellType(result).base, waZctDecRef)
|
extGetCellType(result).base, waZctDecRef)
|
||||||
|
|
||||||
# XXX: zeroing out the memory can still result in crashes if a wiped-out
|
# XXX: zeroing out the memory can still result in crashes if a wiped-out
|
||||||
|
|
@ -327,7 +322,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
# presence of user defined destructors, the user will expect the cell to be
|
# presence of user defined destructors, the user will expect the cell to be
|
||||||
# "destroyed" thus creating the same problem. We can destroy the cell in the
|
# "destroyed" thus creating the same problem. We can destroy the cell in the
|
||||||
# finalizer of the sequence, but this makes destruction non-deterministic.
|
# finalizer of the sequence, but this makes destruction non-deterministic.
|
||||||
zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
|
zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +%
|
||||||
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
||||||
result.len = newLen
|
result.len = newLen
|
||||||
|
|
||||||
|
|
@ -339,10 +334,11 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
||||||
else:
|
else:
|
||||||
when defined(nimIncrSeqV3):
|
when defined(nimIncrSeqV3):
|
||||||
let elemSize = typ.base.size
|
let elemSize = typ.base.size
|
||||||
|
let elemAlign = typ.base.align
|
||||||
if s.space < newLen:
|
if s.space < newLen:
|
||||||
let r = max(resize(s.space), newLen)
|
let r = max(resize(s.space), newLen)
|
||||||
result = cast[PGenericSeq](newSeq(typ, r))
|
result = cast[PGenericSeq](newSeq(typ, r))
|
||||||
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * elemSize)
|
copyMem(result +! align(GenericSeqSize, elemAlign), s +! align(GenericSeqSize, elemAlign), s.len * elemSize)
|
||||||
# since we steal the content from 's', it's crucial to set s's len to 0.
|
# since we steal the content from 's', it's crucial to set s's len to 0.
|
||||||
s.len = 0
|
s.len = 0
|
||||||
elif newLen < s.len:
|
elif newLen < s.len:
|
||||||
|
|
@ -354,7 +350,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
||||||
if ntfNoRefs notin typ.base.flags:
|
if ntfNoRefs notin typ.base.flags:
|
||||||
for i in newLen..result.len-1:
|
for i in newLen..result.len-1:
|
||||||
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
|
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
|
||||||
GenericSeqSize +% (i*%elemSize)),
|
align(GenericSeqSize, elemAlign) +% (i*%elemSize)),
|
||||||
extGetCellType(result).base, waZctDecRef)
|
extGetCellType(result).base, waZctDecRef)
|
||||||
|
|
||||||
# XXX: zeroing out the memory can still result in crashes if a wiped-out
|
# XXX: zeroing out the memory can still result in crashes if a wiped-out
|
||||||
|
|
@ -363,7 +359,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
||||||
# presence of user defined destructors, the user will expect the cell to be
|
# presence of user defined destructors, the user will expect the cell to be
|
||||||
# "destroyed" thus creating the same problem. We can destroy the cell in the
|
# "destroyed" thus creating the same problem. We can destroy the cell in the
|
||||||
# finalizer of the sequence, but this makes destruction non-deterministic.
|
# finalizer of the sequence, but this makes destruction non-deterministic.
|
||||||
zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
|
zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +%
|
||||||
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
||||||
else:
|
else:
|
||||||
result = s
|
result = s
|
||||||
|
|
|
||||||
17
tests/collections/thardalignmentconstraint.nim
Normal file
17
tests/collections/thardalignmentconstraint.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
|
# does not yet work
|
||||||
|
|
||||||
|
{.passC: "-march=native".}
|
||||||
|
|
||||||
|
type
|
||||||
|
m256d {.importc: "__m256d", header: "immintrin.h".} = object
|
||||||
|
|
||||||
|
proc set1(x: float): m256d {.importc: "_mm256_set1_pd", header: "immintrin.h".}
|
||||||
|
|
||||||
|
for _ in 1..1000:
|
||||||
|
var x = newSeq[m256d](1)
|
||||||
|
x[0] = set1(1.0) # test if operation causes segfault
|
||||||
|
doAssert (cast[uint](x[0].addr) and 31) == 0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue