allocators.nim: minor typo

This commit is contained in:
Andreas Rumpf
2018-01-04 14:16:33 +01:00
parent 64d583d6ca
commit 80fef7c818
4 changed files with 332 additions and 0 deletions

49
lib/core/allocators.nim Normal file
View File

@@ -0,0 +1,49 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2017 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
type
TypeLayout* = object
size*, alignment*: int
destructor*: proc (self: pointer; a: Allocator) {.nimcall.}
trace*: proc (self: pointer; a: Allocator) {.nimcall.}
when false:
construct*: proc (self: pointer; a: Allocator) {.nimcall.}
copy*, deepcopy*, sink*: proc (self, other: pointer; a: Allocator) {.nimcall.}
Allocator* {.inheritable.} = ptr object
alloc*: proc (a: Allocator; size: int; alignment = 8): pointer {.nimcall.}
dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall.}
realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.}
visit*: proc (fieldAddr: ptr pointer; a: Allocator) {.nimcall.}
#proc allocArray(a: Allocator; L, elem: TypeLayout; n: int): pointer
#proc deallocArray(a: Allocator; p: pointer; L, elem: TypeLayout; n: int)
proc getTypeLayout*(t: typedesc): ptr TypeLayout {.magic: "getTypeLayout".}
var
currentAllocator {.threadvar.}: Allocator
proc getCurrentAllocator*(): Allocator =
result = currentAllocator
proc setCurrentAllocator*(a: Allocator) =
currentAllocator = a
proc alloc*(size: int): pointer =
let a = getCurrentAllocator()
result = a.alloc(a, size)
proc dealloc*(p: pointer; size: int) =
let a = getCurrentAllocator()
a.dealloc(a, size)
proc realloc*(p: pointer; oldSize, newSize: int): pointer =
let a = getCurrentAllocator()
result = a.realloc(a, oldSize, newSize)

55
lib/core/refs.nim Normal file
View File

@@ -0,0 +1,55 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2017 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Default ref implementation used by Nim's core.
import allocators
type
TracingGc = ptr object of Allocator
GcHeader = object
t: ptr TypeLayout
GcFrame {.core.} = object
prev: ptr GcFrame
marker: proc (self: GcFrame; a: Allocator)
proc `=trace`[T](a: ref T) =
if not marked(a):
mark(a)
`=trace`(a[])
proc linkGcFrame(f: ptr GcFrame) {.core.}
proc unlinkGcFrame() {.core.}
proc setGcFrame(f: ptr GcFrame) {.core.}
proc registerGlobal(p: pointer; t: ptr TypeLayout) {.core.}
proc unregisterGlobal(p: pointer; t: ptr TypeLayout) {.core.}
proc registerThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
proc unregisterThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
proc newImpl(t: ptr TypeLayout): pointer =
let a = getCurrentAllocator()
let r = cast[ptr GcHeader](a.alloc(a, t.size + sizeof(GcHeader), t.alignment))
r.typ = t
result = r +! sizeof(GcHeader)
template new*[T](x: var ref T) =
x = newImpl(getTypeLayout(x))
when false:
# implement these if your GC requires them:
proc writeBarrierLocal() {.core.}
proc writeBarrierGlobal() {.core.}
proc writeBarrierGeneric() {.core.}

117
lib/core/seqs.nim Normal file
View File

@@ -0,0 +1,117 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2017 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import allocators
## Default seq implementation used by Nim's core.
type
seq*[T] = object
len, cap: int
data: ptr UncheckedArray[T]
template frees(s) = dealloc(s.data, s.cap * sizeof(T))
# XXX make code memory safe for overflows in '*'
proc nimSeqLiteral[T](x: openArray[T]): seq[T] {.core.} =
seq[T](len: x.len, cap: x.len, data: x)
when defined(nimHasTrace):
proc `=trace`[T](s: seq[T]; a: Allocator) =
for i in 0 ..< s.len: `=trace`(s.data[i], a)
proc `=destroy`[T](x: var seq[T]) =
if x.data != nil:
when not supportsCopyMem(T):
for i in 0..<x.len: `=destroy`(x[i])
frees(x)
x.data = nil
x.len = 0
x.cap = 0
proc `=`[T](a: var seq[T]; b: seq[T]) =
if a.data == b.data: return
if a.data != nil:
frees(a)
a.data = nil
a.len = b.len
a.cap = b.cap
if b.data != nil:
a.data = cast[type(a.data)](alloc(a.cap * sizeof(T)))
when supportsCopyMem(T):
copyMem(a.data, b.data, a.cap * sizeof(T))
else:
for i in 0..<a.len:
a.data[i] = b.data[i]
proc `=sink`[T](a: var seq[T]; b: seq[T]) =
if a.data != nil and a.data != b.data:
frees(a)
a.len = b.len
a.cap = b.cap
a.data = b.data
proc resize[T](s: var seq[T]) =
let old = s.cap
if old == 0: s.cap = 8
else: s.cap = (s.cap * 3) shr 1
s.data = cast[type(s.data)](realloc(s.data, old * sizeof(T), s.cap * sizeof(T)))
proc reserveSlot[T](x: var seq[T]): ptr T =
if x.len >= x.cap: resize(x)
result = addr(x.data[x.len])
inc x.len
template add*[T](x: var seq[T]; y: T) =
reserveSlot(x)[] = y
proc shrink*[T](x: var seq[T]; newLen: int) =
assert newLen <= x.len
assert newLen >= 0
when not supportsCopyMem(T):
for i in countdown(x.len - 1, newLen - 1):
`=destroy`(x.data[i])
x.len = newLen
proc grow*[T](x: var seq[T]; newLen: int; value: T) =
if newLen <= x.len: return
assert newLen >= 0
if x.cap == 0: x.cap = newLen
else: x.cap = max(newLen, (x.cap * 3) shr 1)
x.data = cast[type(x.data)](realloc(x.data, x.cap * sizeof(T)))
for i in x.len..<newLen:
x.data[i] = value
x.len = newLen
template default[T](t: typedesc[T]): T =
var v: T
v
proc setLen*[T](x: var seq[T]; newLen: int) {.deprecated.} =
if newlen < x.len: shrink(x, newLen)
else: grow(x, newLen, default(T))
template `[]`*[T](x: seq[T]; i: Natural): T =
assert i < x.len
x.data[i]
template `[]=`*[T](x: seq[T]; i: Natural; y: T) =
assert i < x.len
x.data[i] = y
proc `@`*[T](elems: openArray[T]): seq[T] =
result.cap = elems.len
result.len = elems.len
result.data = cast[type(result.data)](alloc(result.cap * sizeof(T)))
when supportsCopyMem(T):
copyMem(result.data, unsafeAddr(elems[0]), result.cap * sizeof(T))
else:
for i in 0..<result.len:
result.data[i] = elems[i]
proc len*[T](x: seq[T]): int {.inline.} = x.len

111
lib/core/strs.nim Normal file
View File

@@ -0,0 +1,111 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2017 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Default string implementation used by Nim's core.
import allocators
type
string {.core.} = object
len, cap: int
data: ptr UncheckedArray[char]
proc nimStringLiteral(x: cstring; len: int): string {.core.} =
string(len: len, cap: len, data: x)
template frees(s) = dealloc(s.data, s.cap + 1)
proc `=destroy`(s: var string) =
if s.data != nil:
frees(s)
s.data = nil
s.len = 0
s.cap = 0
proc `=sink`(a: var string, b: string) =
# we hope this is optimized away for not yet alive objects:
if a.data != nil and a.data != b.data:
frees(a)
a.len = b.len
a.cap = b.cap
a.data = b.data
proc `=`(a: var string; b: string) =
if a.data != nil and a.data != b.data:
frees(a)
a.data = nil
a.len = b.len
a.cap = b.cap
if b.data != nil:
a.data = cast[type(a.data)](alloc(a.cap + 1))
copyMem(a.data, b.data, a.cap+1)
proc resize(s: var string) =
let old = s.cap
if old == 0: s.cap = 8
else: s.cap = (s.cap * 3) shr 1
s.data = cast[type(s.data)](realloc(s.data, old + 1, s.cap + 1))
proc add*(s: var string; c: char) =
if s.len >= s.cap: resize(s)
s.data[s.len] = c
s.data[s.len+1] = '\0'
inc s.len
proc ensure(s: var string; newLen: int) =
let old = s.cap
if newLen >= old:
s.cap = max((old * 3) shr 1, newLen)
if s.cap > 0:
s.data = cast[type(s.data)](realloc(s.data, old + 1, s.cap + 1))
proc add*(s: var string; y: string) =
if y.len != 0:
let newLen = s.len + y.len
ensure(s, newLen)
copyMem(addr s.data[len], y.data, y.data.len + 1)
s.len = newLen
proc len*(s: string): int {.inline.} = s.len
proc newString*(len: int): string =
result.len = len
result.cap = len
if len > 0:
result.data = alloc0(len+1)
converter toCString(x: string): cstring {.core.} =
if x.len == 0: cstring"" else: cast[cstring](x.data)
proc newStringOfCap*(cap: int): string =
result.len = 0
result.cap = cap
if cap > 0:
result.data = alloc(cap+1)
proc `&`*(a, b: string): string =
let sum = a.len + b.len
result = newStringOfCap(sum)
result.len = sum
copyMem(addr result.data[0], a.data, a.len)
copyMem(addr result.data[a.len], b.data, b.len)
if sum > 0:
result.data[sum] = '\0'
proc concat(x: openArray[string]): string {.core.} =
## used be the code generator to optimize 'x & y & z ...'
var sum = 0
for i in 0 ..< x.len: inc(sum, x[i].len)
result = newStringOfCap(sum)
sum = 0
for i in 0 ..< x.len:
let L = x[i].len
copyMem(addr result.data[sum], x[i].data, L)
inc(sum, L)