summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-12-22 15:04:00 +0100
committerAraq <rumpf_a@web.de>2011-12-22 15:04:00 +0100
commitcd83cc81aa58922e0a8370ae5928d5b5aaa16f84 (patch)
treee3abff5b7a2cd46977e8435a4ebbfdde0c19ba07 /lib
parentf19c1c0f6e93a561dc13ef57d136957edeba9ed4 (diff)
downloadNim-cd83cc81aa58922e0a8370ae5928d5b5aaa16f84.tar.gz
code gen can generate code to keep alive stack roots
Diffstat (limited to 'lib')
-rwxr-xr-xlib/nimbase.h8
-rwxr-xr-xlib/pure/strutils.nim43
-rwxr-xr-xlib/system/alloc.nim19
-rwxr-xr-xlib/system/gc.nim7
4 files changed, 67 insertions, 10 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h
index bc8c3c28c..e2afed8f9 100755
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -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
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 33bb5b5f0..6b6c3861f 100755
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -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)

 

diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 6dee145c8..f33d40b0a 100755
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -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)
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index caab22e34..f13015573 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -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".}