--newruntime: progress

This commit is contained in:
Andreas Rumpf 2019-03-14 19:53:14 +01:00
commit e263702688
15 changed files with 111 additions and 109 deletions

View file

@ -12,7 +12,7 @@ type
ThreadLocal ## the allocator is thread local only.
ZerosMem ## the allocator always zeros the memory on an allocation
Allocator* = ptr AllocatorObj
AllocatorObj* {.inheritable.} = object
AllocatorObj* {.inheritable, compilerproc.} = object
alloc*: proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall, raises: [], tags: [].}
dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall, raises: [], tags: [].}
realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall, raises: [], tags: [].}

View file

@ -38,15 +38,6 @@ type
# we could remove it in non-debug builds but this seems
# unwise.
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
result = strstr(obj.name, subclass) != nil
proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} =
# checks if obj is of type subclass:
if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
template `+!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) +% s)
@ -76,3 +67,12 @@ proc nimDestroyAndDispose(p: pointer) {.compilerRtl.} =
let d = cast[ptr PNimType](p)[].destructor
if d != nil: d(p)
nimRawDispose(p)
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
result = strstr(obj.name, subclass) != nil
proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} =
# checks if obj is of type subclass:
if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")

View file

@ -17,7 +17,7 @@ proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
type
NimSeqPayload[T] = object
cap: int
region: Allocator
allocator: Allocator
data: UncheckedArray[T]
NimSeqV2*[T] = object
@ -52,8 +52,8 @@ when not defined(nimV2):
mixin `=destroy`
when not supportsCopyMem(T):
for i in 0..<x.len: `=destroy`(p.data[i])
if p.region != nil:
p.region.dealloc(p.region, p, payloadSize(p.cap))
if p.allocator != nil:
p.allocator.dealloc(p.allocator, p, payloadSize(p.cap))
x.p = nil
x.len = 0
@ -87,15 +87,15 @@ when not defined(nimV2):
type
PayloadBase = object
cap: int
region: Allocator
allocator: Allocator
proc newSeqPayload(cap, elemSize: int): pointer {.compilerRtl, raises: [].} =
# we have to use type erasure here as Nim does not support generic
# compilerProcs. Oh well, this will all be inlined anyway.
if cap > 0:
let region = getLocalAllocator()
var p = cast[ptr PayloadBase](region.alloc(region, cap * elemSize + sizeof(int) + sizeof(Allocator)))
p.region = region
let allocator = getLocalAllocator()
var p = cast[ptr PayloadBase](allocator.alloc(allocator, cap * elemSize + sizeof(int) + sizeof(Allocator)))
p.allocator = allocator
p.cap = cap
result = p
else:
@ -112,12 +112,12 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize: int): pointer {.
# Note: this means we cannot support things that have internal pointers as
# they get reallocated here. This needs to be documented clearly.
var p = cast[ptr PayloadBase](p)
let region = if p.region == nil: getLocalAllocator() else: p.region
let allocator = if p.allocator == nil: getLocalAllocator() else: p.allocator
let cap = max(resize(p.cap), len+addlen)
var q = cast[ptr PayloadBase](region.realloc(region, p,
var q = cast[ptr PayloadBase](allocator.realloc(allocator, p,
sizeof(int) + sizeof(Allocator) + elemSize * p.cap,
sizeof(int) + sizeof(Allocator) + elemSize * cap))
q.region = region
q.allocator = allocator
q.cap = cap
result = q

View file

@ -28,7 +28,7 @@ import allocators
type
NimStrPayload {.core.} = object
cap: int
region: Allocator
allocator: Allocator
data: UncheckedArray[char]
NimStringV2 {.core.} = object
@ -37,7 +37,7 @@ type
const nimStrVersion {.core.} = 2
template isLiteral(s): bool = s.p == nil or s.p.region == nil
template isLiteral(s): bool = s.p == nil or s.p.allocator == nil
template contentSize(cap): int = cap + 1 + sizeof(int) + sizeof(Allocator)
@ -45,7 +45,7 @@ when not defined(nimV2):
template frees(s) =
if not isLiteral(s):
s.p.region.dealloc(s.p.region, s.p, contentSize(s.p.cap))
s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap))
proc `=destroy`(s: var string) =
var a = cast[ptr NimStringV2](addr s)
@ -72,12 +72,12 @@ when not defined(nimV2):
# we can shallow copy literals:
a.p = b.p
else:
let region = if a.p != nil and a.p.region != nil: a.p.region else: getLocalAllocator()
let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
# we have to allocate the 'cap' here, consider
# 'let y = newStringOfCap(); var x = y'
# on the other hand... These get turned into moves now.
a.p = cast[ptr NimStrPayload](region.alloc(region, contentSize(b.len)))
a.p.region = region
a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
a.p.allocator = allocator
a.p.cap = b.len
copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
@ -90,16 +90,16 @@ proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
if isLiteral(s):
let oldP = s.p
# can't mutate a literal, so we need a fresh copy here:
let region = getLocalAllocator()
s.p = cast[ptr NimStrPayload](region.alloc(region, contentSize(s.len + addlen)))
s.p.region = region
let allocator = getLocalAllocator()
s.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(s.len + addlen)))
s.p.allocator = allocator
s.p.cap = s.len + addlen
if s.len > 0:
# we are about to append, so there is no need to copy the \0 terminator:
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
elif s.len + addlen > s.p.cap:
let cap = max(s.len + addlen, resize(s.p.cap))
s.p = cast[ptr NimStrPayload](s.p.region.realloc(s.p.region, s.p,
s.p = cast[ptr NimStrPayload](s.p.allocator.realloc(s.p.allocator, s.p,
oldSize = contentSize(s.p.cap),
newSize = contentSize(cap)))
s.p.cap = cap
@ -114,9 +114,9 @@ proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerProc.} =
if len <= 0:
result = NimStringV2(len: 0, p: nil)
else:
let region = getLocalAllocator()
var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(len)))
p.region = region
let allocator = getLocalAllocator()
var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(len)))
p.allocator = allocator
p.cap = len
if len > 0:
# we are about to append, so there is no need to copy the \0 terminator:
@ -147,9 +147,9 @@ proc rawNewString(space: int): NimStringV2 {.compilerProc.} =
if space <= 0:
result = NimStringV2(len: 0, p: nil)
else:
let region = getLocalAllocator()
var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(space)))
p.region = region
let allocator = getLocalAllocator()
var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(space)))
p.allocator = allocator
p.cap = space
result = NimStringV2(len: 0, p: p)
@ -157,9 +157,9 @@ proc mnewString(len: int): NimStringV2 {.compilerProc.} =
if len <= 0:
result = NimStringV2(len: 0, p: nil)
else:
let region = getLocalAllocator()
var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(len)))
p.region = region
let allocator = getLocalAllocator()
var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(len)))
p.allocator = allocator
p.cap = len
result = NimStringV2(len: len, p: p)