mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 02:43:41 +00:00
code gen can generate code to keep alive stack roots
This commit is contained in:
@@ -16,6 +16,7 @@ __GNUC__
|
||||
__DMC__
|
||||
__POCC__
|
||||
__TINYC__
|
||||
__clang__
|
||||
*/
|
||||
|
||||
|
||||
@@ -437,4 +438,11 @@ __declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
||||
# define unlikely(x) (x)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
|
||||
# define GC_GUARD __attribute__ ((cleanup(GCGuard)))
|
||||
#else
|
||||
# define GC_GUARD
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -699,7 +699,7 @@ proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
|
||||
rtl, extern: "nsuFindStr".} =
|
||||
## Searches for `sub` in `s` starting at position `start`. Searching is
|
||||
## case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||
var a: TSkipTable
|
||||
var a {.noinit.}: TSkipTable
|
||||
preprocessSub(sub, a)
|
||||
result = findAux(s, sub, start, a)
|
||||
|
||||
@@ -742,7 +742,7 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} =
|
||||
proc replace*(s, sub: string, by = ""): string {.noSideEffect,
|
||||
rtl, extern: "nsuReplaceStr".} =
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
var a: TSkipTable
|
||||
var a {.noinit.}: TSkipTable
|
||||
result = ""
|
||||
preprocessSub(sub, a)
|
||||
var i = 0
|
||||
@@ -989,7 +989,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||
## after the decimal point for Nimrod's ``biggestFloat`` type.
|
||||
const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
|
||||
var
|
||||
frmtstr: array[0..5, char]
|
||||
frmtstr {.noinit.}: array[0..5, char]
|
||||
buf: array[0..80, char]
|
||||
frmtstr[0] = '%'
|
||||
frmtstr[1] = '#'
|
||||
@@ -1018,16 +1018,41 @@ proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
||||
## after the decimal point for Nimrod's ``float`` type.
|
||||
result = formatBiggestFloat(f, format, precision)
|
||||
|
||||
proc formatSize*(bytes: biggestInt, decimalSep = '.'): string =
|
||||
## Rounds and formats `bytes`. Examples:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## formatSize(1'i64 shl 31 + 300'i64) == "4GB"
|
||||
## formatSize(4096) == "4KB"
|
||||
##
|
||||
template frmt(a, b, c: expr): expr =
|
||||
let bs = $b
|
||||
insertSep($a) & decimalSep & bs.substr(0, 2) & c
|
||||
let gigabytes = bytes shr 30
|
||||
let megabytes = bytes shr 20
|
||||
let kilobytes = bytes shr 10
|
||||
if gigabytes != 0:
|
||||
result = frmt(gigabytes, megabytes, "GB")
|
||||
elif megabytes != 0:
|
||||
result = frmt(megabytes, kilobytes, "MB")
|
||||
elif kilobytes != 0:
|
||||
result = frmt(kilobytes, bytes, "KB")
|
||||
else:
|
||||
result = insertSep($bytes) & "B"
|
||||
|
||||
{.pop.}
|
||||
|
||||
when isMainModule:
|
||||
assert align("abc", 4) == " abc"
|
||||
assert align("a", 0) == "a"
|
||||
assert align("1232", 6) == " 1232"
|
||||
doAssert align("abc", 4) == " abc"
|
||||
doAssert align("a", 0) == "a"
|
||||
doAssert align("1232", 6) == " 1232"
|
||||
echo wordWrap(""" this is a long text -- muchlongerthan10chars and here
|
||||
it goes""", 10, false)
|
||||
assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||
assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
||||
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
||||
|
||||
assert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
||||
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
||||
echo formatSize(1'i64 shl 31 + 300'i64) # == "4,GB"
|
||||
echo formatSize(1'i64 shl 31)
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ proc getMaxMem(a: var TMemRegion): int =
|
||||
# Since we update maxPagesCount only when freeing pages,
|
||||
# maxPagesCount may not be up to date. Thus we use the
|
||||
# maximum of these both values here:
|
||||
return max(a.currMem, a.maxMem)
|
||||
result = max(a.currMem, a.maxMem)
|
||||
|
||||
proc llAlloc(a: var TMemRegion, size: int): pointer =
|
||||
# *low-level* alloc for the memory managers data structures. Deallocation
|
||||
@@ -550,6 +550,23 @@ proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
|
||||
var c = cast[PBigChunk](c)
|
||||
result = p == addr(c.data) and cast[ptr TFreeCell](p).zeroField >% 1
|
||||
|
||||
proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
|
||||
if isAccessible(a, p):
|
||||
var c = pageAddr(p)
|
||||
if not chunkUnused(c):
|
||||
if isSmallChunk(c):
|
||||
var c = cast[PSmallChunk](c)
|
||||
var offset = (cast[TAddress](p) and (PageSize-1)) -%
|
||||
smallChunkOverhead()
|
||||
if c.acc >% offset:
|
||||
var d = cast[ptr TFreeCell](cast[TAddress](addr(c.data)) +%
|
||||
offset -% (offset %% c.size))
|
||||
if d.zeroField >% 1: result = d
|
||||
else:
|
||||
var c = cast[PBigChunk](c)
|
||||
var d = addr(c.data)
|
||||
if p >= d and cast[ptr TFreeCell](d).zeroField >% 1: result = d
|
||||
|
||||
proc ptrSize(p: pointer): int =
|
||||
var x = cast[pointer](cast[TAddress](p) -% sizeof(TFreeCell))
|
||||
result = pageAddr(x).size - sizeof(TFreeCell)
|
||||
|
||||
@@ -579,6 +579,13 @@ proc nimKeepAlive(p: PGenericSeq) {.compilerRtl, noinline.} =
|
||||
if isAllocatedPtr(gch.region, c):
|
||||
c.refcount = c.refcount or rcMarked
|
||||
|
||||
proc nimGCFrame(p: pointer) {.compilerRtl, noinline.} =
|
||||
# 'cast' is correct here! no offset to add:
|
||||
var c = cast[PCell](p)
|
||||
var x = cast[TAddress](c)
|
||||
if x <% PageSize and (x and (MemAlign-1)) == 0:
|
||||
c.refcount = c.refcount or rcMarked
|
||||
|
||||
proc markThreadStacks(gch: var TGcHeap) =
|
||||
when hasThreadSupport and hasSharedHeap:
|
||||
{.error: "not fully implemented".}
|
||||
|
||||
Reference in New Issue
Block a user