make at least bootstrapping work

This commit is contained in:
Araq 2018-08-05 14:17:24 +02:00
commit 7ac6462cbd
81 changed files with 1314 additions and 425 deletions

View file

@ -116,6 +116,8 @@ type
nextChunkSize: int
bottomData: AvlNode
heapLinks: HeapLinks
when defined(nimTypeNames):
allocCounter, deallocCounter: int
const
fsLookupTable: array[byte, int8] = [
@ -434,8 +436,9 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
a.nextChunkSize = PageSize*4
else:
a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2)
var size = size
a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize)
var size = size
if size > a.nextChunkSize:
result = cast[PBigChunk](osAllocPages(size))
else:
@ -737,6 +740,8 @@ when false:
result = nil
proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
when defined(nimTypeNames):
inc(a.allocCounter)
sysAssert(allocInv(a), "rawAlloc: begin")
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
sysAssert(requestedSize >= sizeof(FreeCell), "rawAlloc: requested size too small")
@ -810,6 +815,8 @@ proc rawAlloc0(a: var MemRegion, requestedSize: int): pointer =
zeroMem(result, requestedSize)
proc rawDealloc(a: var MemRegion, p: pointer) =
when defined(nimTypeNames):
inc(a.deallocCounter)
#sysAssert(isAllocatedPtr(a, p), "rawDealloc: no allocated pointer")
sysAssert(allocInv(a), "rawDealloc: begin")
var c = pageAddr(p)
@ -975,6 +982,10 @@ proc getOccupiedMem(a: MemRegion): int {.inline.} =
result = a.occ
# a.currMem - a.freeMem
when defined(nimTypeNames):
proc getMemCounters(a: MemRegion): (int, int) {.inline.} =
(a.allocCounter, a.deallocCounter)
# ---------------------- thread memory region -------------------------------
template instantiateForRegion(allocator: untyped) =
@ -1018,6 +1029,9 @@ template instantiateForRegion(allocator: untyped) =
proc getOccupiedMem(): int = return allocator.occ #getTotalMem() - getFreeMem()
proc getMaxMem*(): int = return getMaxMem(allocator)
when defined(nimTypeNames):
proc getMemCounters*(): (int, int) = getMemCounters(allocator)
# -------------------- shared heap region ----------------------------------
when hasThreadSupport:
var sharedHeap: MemRegion

View file

@ -27,6 +27,9 @@ proc c_strcmp(a, b: cstring): cint {.
importc: "strcmp", header: "<string.h>", noSideEffect.}
proc c_strlen(a: cstring): csize {.
importc: "strlen", header: "<string.h>", noSideEffect.}
proc c_abort() {.
importc: "abort", header: "<stdlib.h>", noSideEffect.}
when defined(linux) and defined(amd64):
type

View file

@ -548,7 +548,10 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
gcTrace(res, csAllocated)
track("growObj old", ol, 0)
track("growObj new", res, newsize)
when reallyDealloc:
when defined(nimIncrSeqV3):
# since we steal the old seq's contents, we set the old length to 0.
cast[PGenericSeq](old).len = 0
elif reallyDealloc:
sysAssert(allocInv(gch.region), "growObj before dealloc")
if ol.refcount shr rcShift <=% 1:
# free immediately to save space:

View file

@ -57,6 +57,9 @@ when defined(nimTypeNames):
for i in 0 .. n-1:
c_fprintf(stdout, "[Heap] %s: #%ld; bytes: %ld\n", a[i][0], a[i][1], a[i][2])
c_fprintf(stdout, "[Heap] total number of bytes: %ld\n", totalAllocated)
when defined(nimTypeNames):
let (allocs, deallocs) = getMemCounters()
c_fprintf(stdout, "[Heap] allocs/deallocs: %ld/%ld\n", allocs, deallocs)
when defined(nimGcRefLeak):
proc oomhandler() =

View file

@ -417,12 +417,18 @@ proc setStdIoUnbuffered() =
discard c_setvbuf(stdin, nil, IONBF, 0)
when declared(stdout):
when defined(windows) and compileOption("threads"):
var echoLock: SysLock
initSysLock echoLock
proc echoBinSafe(args: openArray[string]) {.compilerProc.} =
# flockfile deadlocks some versions of Android 5.x.x
when not defined(windows) and not defined(android) and not defined(nintendoswitch):
proc flockfile(f: File) {.importc, noDecl.}
proc funlockfile(f: File) {.importc, noDecl.}
flockfile(stdout)
when defined(windows) and compileOption("threads"):
acquireSys echoLock
for s in args:
discard c_fwrite(s.cstring, s.len, 1, stdout)
const linefeed = "\n" # can be 1 or more chars
@ -430,5 +436,7 @@ when declared(stdout):
discard c_fflush(stdout)
when not defined(windows) and not defined(android) and not defined(nintendoswitch):
funlockfile(stdout)
when defined(windows) and compileOption("threads"):
releaseSys echoLock
{.pop.}

View file

@ -144,8 +144,13 @@ proc addChar(s: NimString, c: char): NimString =
result = s
if result.len >= result.space:
let r = resize(result.space)
result = cast[NimString](growObj(result,
sizeof(TGenericSeq) + r + 1))
when defined(nimIncrSeqV3):
result = rawNewStringNoInit(r)
result.len = s.len
copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len+1)
else:
result = cast[NimString](growObj(result,
sizeof(TGenericSeq) + r + 1))
result.reserved = r
result.data[result.len] = c
result.data[result.len+1] = '\0'
@ -188,8 +193,13 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
elif dest.len + addlen <= dest.space:
result = dest
else: # slow path:
var sp = max(resize(dest.space), dest.len + addlen)
result = cast[NimString](growObj(dest, sizeof(TGenericSeq) + sp + 1))
let sp = max(resize(dest.space), dest.len + addlen)
when defined(nimIncrSeqV3):
result = rawNewStringNoInit(sp)
result.len = dest.len
copyMem(addr result.data[0], unsafeAddr(dest.data[0]), dest.len+1)
else:
result = cast[NimString](growObj(dest, sizeof(TGenericSeq) + sp + 1))
result.reserved = sp
#result = rawNewString(sp)
#copyMem(result, dest, dest.len + sizeof(TGenericSeq))
@ -212,7 +222,15 @@ proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
elif n <= s.space:
result = s
else:
result = resizeString(s, n)
let sp = max(resize(s.space), newLen)
when defined(nimIncrSeqV3):
result = rawNewStringNoInit(sp)
result.len = s.len
copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len+1)
zeroMem(addr result.data[s.len], newLen - s.len)
result.reserved = sp
else:
result = resizeString(s, n)
result.len = n
result.data[n] = '\0'
@ -242,6 +260,9 @@ proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
GenericSeqSize))
result.reserved = r
template `+!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) +% s)
proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.} =
if s == nil:
result = cast[PGenericSeq](newSeq(typ, 1))
@ -250,9 +271,16 @@ proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.} =
result = s
if result.len >= result.space:
let r = resize(result.space)
result = cast[PGenericSeq](growObj(result, typ.base.size * r +
when defined(nimIncrSeqV3):
result = cast[PGenericSeq](newSeq(typ, r))
result.len = s.len
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * typ.base.size)
# since we steal the content from 's', it's crucial to set s's len to 0.
s.len = 0
else:
result = cast[PGenericSeq](growObj(result, typ.base.size * r +
GenericSeqSize))
result.reserved = r
result.reserved = r
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
compilerRtl, inl.} =
@ -296,7 +324,40 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
compilerRtl.} =
sysAssert typ.kind == tySequence, "setLengthSeqV2: type is not a seq"
if s == nil:
result = cast[PGenericSeq](newSeq(typ, newLen))
else:
result = setLengthSeq(s, typ.base.size, newLen)
when defined(nimIncrSeqV3):
let elemSize = typ.base.size
if s.space < newLen:
let r = max(resize(s.space), newLen)
result = cast[PGenericSeq](newSeq(typ, r))
copyMem(result +! GenericSeqSize, s +! GenericSeqSize, s.len * elemSize)
# since we steal the content from 's', it's crucial to set s's len to 0.
s.len = 0
elif newLen < s.len:
result = s
# we need to decref here, otherwise the GC leaks!
when not defined(boehmGC) and not defined(nogc) and
not defined(gcMarkAndSweep) and not defined(gogc) and
not defined(gcRegions):
if ntfNoRefs notin typ.base.flags:
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# XXX: zeroing out the memory can still result in crashes if a wiped-out
# cell is aliased by another pointer (ie proc parameter or a let variable).
# This is a tough problem, because even if we don't zeroMem here, in the
# presence of user defined destructors, the user will expect the cell to be
# "destroyed" thus creating the same problem. We can destoy the cell in the
# finalizer of the sequence, but this makes destruction non-deterministic.
zeroMem(cast[pointer](cast[ByteAddress](result) +% GenericSeqSize +%
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
else:
result = s
result.len = newLen
else:
result = setLengthSeq(s, typ.base.size, newLen)