improvements to get code size down for programs that don't use GC
This commit is contained in:
parent
c9d21164be
commit
e25384db89
18 changed files with 642 additions and 181 deletions
|
|
@ -1387,7 +1387,7 @@ const nimrodStackTrace = compileOption("stacktrace")
|
|||
# of the code
|
||||
|
||||
var
|
||||
dbgLineHook*: proc = nil
|
||||
dbgLineHook*: proc
|
||||
## set this variable to provide a procedure that should be called before
|
||||
## each executed instruction. This should only be used by debuggers!
|
||||
## Only code compiled with the ``debugger:on`` switch calls this hook.
|
||||
|
|
@ -1397,6 +1397,25 @@ var
|
|||
## application code should never set this hook! You better know what you
|
||||
## do when setting this. If ``raiseHook`` returns false, the exception
|
||||
## is caught and does not propagate further through the call stack.
|
||||
|
||||
outOfMemHook*: proc
|
||||
## set this variable to provide a procedure that should be called
|
||||
## in case of an `out of memory`:idx: event. The standard handler
|
||||
## writes an error message and terminates the program. `outOfMemHook` can
|
||||
## be used to raise an exception in case of OOM like so:
|
||||
##
|
||||
## code-block:: nimrod
|
||||
## var gOutOfMem: ref EOutOfMemory
|
||||
## new(gOutOfMem) # need to be allocated *before* OOM really happened!
|
||||
## gOutOfMem.msg = "out of memory"
|
||||
##
|
||||
## proc handleOOM() =
|
||||
## raise gOutOfMem
|
||||
##
|
||||
## system.outOfMemHook = handleOOM
|
||||
##
|
||||
## If the handler does not raise an exception, ordinary control flow
|
||||
## continues and the program is terminated.
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
|
|
@ -1710,25 +1729,6 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
|||
# as it would recurse endlessly!
|
||||
include "system/arithm"
|
||||
{.pop.} # stack trace
|
||||
|
||||
include "system/sysio"
|
||||
|
||||
iterator lines*(filename: string): string =
|
||||
## Iterate over any line in the file named `filename`.
|
||||
## If the file does not exist `EIO` is raised.
|
||||
var f = open(filename)
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
Close(f)
|
||||
|
||||
iterator lines*(f: TFile): string =
|
||||
## Iterate over any line in the file `f`.
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
|
||||
include "system/dyncalls"
|
||||
include "system/sets"
|
||||
|
|
@ -1763,6 +1763,25 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
|||
include "system/sysstr"
|
||||
{.pop.}
|
||||
|
||||
include "system/sysio"
|
||||
|
||||
iterator lines*(filename: string): string =
|
||||
## Iterate over any line in the file named `filename`.
|
||||
## If the file does not exist `EIO` is raised.
|
||||
var f = open(filename)
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
Close(f)
|
||||
|
||||
iterator lines*(f: TFile): string =
|
||||
## Iterate over any line in the file `f`.
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
|
||||
include "system/assign"
|
||||
include "system/repr"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -138,10 +138,8 @@ proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
|
|||
write(stdout, "*** endb| (procedure name not available) ***\n")
|
||||
|
||||
proc dbgShowExecutionPoint() =
|
||||
ThreadGlobals()
|
||||
write(stdout, "*** endb| " & $(||framePtr).filename &
|
||||
"(" & $(||framePtr).line & ") " &
|
||||
$(||framePtr).procname & " ***\n")
|
||||
write(stdout, "*** endb| " & $framePtr.filename &
|
||||
"(" & $framePtr.line & ") " & $framePtr.procname & " ***\n")
|
||||
|
||||
when defined(windows) or defined(dos) or defined(os2):
|
||||
{.define: FileSystemCaseInsensitive.}
|
||||
|
|
@ -172,10 +170,9 @@ proc fileMatches(c, bp: cstring): bool =
|
|||
return true
|
||||
|
||||
proc dbgBreakpointReached(line: int): int =
|
||||
ThreadGlobals()
|
||||
for i in 0..dbgBPlen-1:
|
||||
if line >= dbgBP[i].low and line <= dbgBP[i].high and
|
||||
fileMatches((||framePtr).filename, dbgBP[i].filename): return i
|
||||
fileMatches(framePtr.filename, dbgBP[i].filename): return i
|
||||
return -1
|
||||
|
||||
proc scanAndAppendWord(src: string, a: var string, start: int): int =
|
||||
|
|
@ -257,7 +254,6 @@ proc hasExt(s: string): bool =
|
|||
return false
|
||||
|
||||
proc setBreakPoint(s: string, start: int) =
|
||||
ThreadGlobals()
|
||||
var dbgTemp: string
|
||||
var i = scanWord(s, dbgTemp, start)
|
||||
if i <= start:
|
||||
|
|
@ -272,7 +268,7 @@ proc setBreakPoint(s: string, start: int) =
|
|||
i = scanNumber(s, dbgBP[x].low, i)
|
||||
if dbgBP[x].low == 0:
|
||||
# set to current line:
|
||||
dbgBP[x].low = (||framePtr).line
|
||||
dbgBP[x].low = framePtr.line
|
||||
i = scanNumber(s, dbgBP[x].high, i)
|
||||
if dbgBP[x].high == 0: # set to low:
|
||||
dbgBP[x].high = dbgBP[x].low
|
||||
|
|
@ -281,7 +277,7 @@ proc setBreakPoint(s: string, start: int) =
|
|||
if not hasExt(dbgTemp): add(dbgTemp, ".nim")
|
||||
dbgBP[x].filename = dbgTemp
|
||||
else: # use current filename
|
||||
dbgBP[x].filename = $(||framePtr).filename
|
||||
dbgBP[x].filename = $framePtr.filename
|
||||
# skip whitespace:
|
||||
while s[i] in {' ', '\t'}: inc(i)
|
||||
if s[i] != '\0':
|
||||
|
|
@ -350,10 +346,9 @@ proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
|
|||
|
||||
proc CommandPrompt() =
|
||||
# if we return from this routine, user code executes again
|
||||
ThreadGlobals()
|
||||
var
|
||||
again = True
|
||||
dbgFramePtr = ||framePtr # for going down and up the stack
|
||||
dbgFramePtr = framePtr # for going down and up the stack
|
||||
dbgDown = 0 # how often we did go down
|
||||
|
||||
while again:
|
||||
|
|
@ -370,11 +365,11 @@ proc CommandPrompt() =
|
|||
again = false
|
||||
of "n", "next":
|
||||
dbgState = dbStepOver
|
||||
dbgSkipToFrame = ||framePtr
|
||||
dbgSkipToFrame = framePtr
|
||||
again = false
|
||||
of "f", "skipcurrent":
|
||||
dbgState = dbSkipCurrent
|
||||
dbgSkipToFrame = (||framePtr).prev
|
||||
dbgSkipToFrame = framePtr.prev
|
||||
again = false
|
||||
of "c", "continue":
|
||||
dbgState = dbBreakpoints
|
||||
|
|
@ -405,7 +400,7 @@ proc CommandPrompt() =
|
|||
if dbgDown <= 0:
|
||||
debugOut("[Warning] cannot go up any further ")
|
||||
else:
|
||||
dbgFramePtr = ||framePtr
|
||||
dbgFramePtr = framePtr
|
||||
for j in 0 .. dbgDown-2: # BUGFIX
|
||||
dbgFramePtr = dbgFramePtr.prev
|
||||
dec(dbgDown)
|
||||
|
|
@ -446,17 +441,16 @@ proc endbStep() =
|
|||
CommandPrompt()
|
||||
|
||||
proc checkForBreakpoint() =
|
||||
ThreadGlobals()
|
||||
var i = dbgBreakpointReached((||framePtr).line)
|
||||
var i = dbgBreakpointReached(framePtr.line)
|
||||
if i >= 0:
|
||||
write(stdout, "*** endb| reached ")
|
||||
write(stdout, dbgBP[i].name)
|
||||
write(stdout, " in ")
|
||||
write(stdout, (||framePtr).filename)
|
||||
write(stdout, framePtr.filename)
|
||||
write(stdout, "(")
|
||||
write(stdout, (||framePtr).line)
|
||||
write(stdout, framePtr.line)
|
||||
write(stdout, ") ")
|
||||
write(stdout, (||framePtr).procname)
|
||||
write(stdout, framePtr.procname)
|
||||
write(stdout, " ***\n")
|
||||
CommandPrompt()
|
||||
|
||||
|
|
@ -487,8 +481,7 @@ proc endb(line: int) {.compilerproc.} =
|
|||
# Thus, it must have as few parameters as possible to keep the
|
||||
# code size small!
|
||||
# Check if we are at an enabled breakpoint or "in the mood"
|
||||
ThreadGlobals()
|
||||
(||framePtr).line = line # this is done here for smaller code size!
|
||||
framePtr.line = line # this is done here for smaller code size!
|
||||
if dbgLineHook != nil: dbgLineHook()
|
||||
case dbgState
|
||||
of dbStepInto:
|
||||
|
|
@ -496,7 +489,7 @@ proc endb(line: int) {.compilerproc.} =
|
|||
dbgShowExecutionPoint()
|
||||
CommandPrompt()
|
||||
of dbSkipCurrent, dbStepOver: # skip current routine
|
||||
if ||framePtr == dbgSkipToFrame:
|
||||
if framePtr == dbgSkipToFrame:
|
||||
dbgShowExecutionPoint()
|
||||
CommandPrompt()
|
||||
else: # breakpoints are wanted though (I guess)
|
||||
|
|
|
|||
|
|
@ -7,16 +7,15 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Exception handling code. This is difficult because it has
|
||||
# to work if there is no more memory (but it doesn't yet!).
|
||||
|
||||
# XXX assertions are unnecessarily complex; system should use their own
|
||||
# assertion mechanism instead!
|
||||
# Exception handling code. Carefully coded so that tiny programs which do not
|
||||
# use the heap (and nor exceptions) do not include the GC or memory allocator.
|
||||
|
||||
var
|
||||
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
|
||||
## for CGI applications
|
||||
isMultiThreaded: bool # true when prog created at least 1 thread
|
||||
stackTraceNewLine*: string ## undocumented feature; it is replaced by ``<br>``
|
||||
## for CGI applications
|
||||
|
||||
template stackTraceNL: expr =
|
||||
(if IsNil(stackTraceNewLine): "\n" else: stackTraceNewLine)
|
||||
|
||||
when not defined(windows) or not defined(guiapp):
|
||||
proc writeToStdErr(msg: CString) = write(stdout, msg)
|
||||
|
|
@ -42,21 +41,6 @@ var
|
|||
# a global variable for the root of all try blocks
|
||||
currException {.rtlThreadVar.}: ref E_Base
|
||||
|
||||
buf {.rtlThreadVar.}: string # cannot be allocated on the stack!
|
||||
assertBuf {.rtlThreadVar.}: string
|
||||
# we need a different buffer for
|
||||
# assert, as it raises an exception and
|
||||
# exception handler needs the buffer too
|
||||
gAssertionFailed {.rtlThreadVar.}: ref EAssertionFailed
|
||||
|
||||
proc initGlobals() =
|
||||
new(gAssertionFailed)
|
||||
buf = newStringOfCap(2000)
|
||||
assertBuf = newStringOfCap(2000)
|
||||
|
||||
when not hasThreadSupport:
|
||||
initGlobals()
|
||||
|
||||
proc pushFrame(s: PFrame) {.compilerRtl, inl.} =
|
||||
s.prev = framePtr
|
||||
framePtr = s
|
||||
|
|
@ -83,8 +67,10 @@ proc popCurrentException {.compilerRtl, inl.} =
|
|||
|
||||
# some platforms have native support for stack traces:
|
||||
const
|
||||
nativeStackTraceSupported = (defined(macosx) or defined(linux)) and
|
||||
not nimrodStackTrace
|
||||
nativeStackTraceSupported = (defined(macosx) or defined(linux)) and
|
||||
not nimrodStackTrace
|
||||
hasSomeStackTrace = nimrodStackTrace or
|
||||
defined(nativeStackTrace) and nativeStackTraceSupported
|
||||
|
||||
when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||
type
|
||||
|
|
@ -126,7 +112,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
|||
add(s, tempDlInfo.dli_sname)
|
||||
else:
|
||||
add(s, '?')
|
||||
add(s, stackTraceNewLine)
|
||||
add(s, stackTraceNL)
|
||||
else:
|
||||
if dlresult != 0 and tempDlInfo.dli_sname != nil and
|
||||
c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32:
|
||||
|
|
@ -181,24 +167,24 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
|
|||
add(s, ')')
|
||||
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
||||
add(s, tempFrames[j].procname)
|
||||
add(s, stackTraceNewLine)
|
||||
add(s, stackTraceNL)
|
||||
|
||||
proc rawWriteStackTrace(s: var string) =
|
||||
when nimrodStackTrace:
|
||||
if framePtr == nil:
|
||||
add(s, "No stack traceback available")
|
||||
add(s, stackTraceNewLine)
|
||||
when hasSomeStackTrace:
|
||||
proc rawWriteStackTrace(s: var string) =
|
||||
when nimrodStackTrace:
|
||||
if framePtr == nil:
|
||||
add(s, "No stack traceback available")
|
||||
add(s, stackTraceNL)
|
||||
else:
|
||||
add(s, "Traceback (most recent call last)")
|
||||
add(s, stackTraceNL)
|
||||
auxWriteStackTrace(framePtr, s)
|
||||
elif defined(nativeStackTrace) and nativeStackTraceSupported:
|
||||
add(s, "Traceback from system (most recent call last)")
|
||||
add(s, stackTraceNL)
|
||||
auxWriteStackTraceWithBacktrace(s)
|
||||
else:
|
||||
add(s, "Traceback (most recent call last)")
|
||||
add(s, stackTraceNewLine)
|
||||
auxWriteStackTrace(framePtr, s)
|
||||
elif defined(nativeStackTrace) and nativeStackTraceSupported:
|
||||
add(s, "Traceback from system (most recent call last)")
|
||||
add(s, stackTraceNewLine)
|
||||
auxWriteStackTraceWithBacktrace(s)
|
||||
else:
|
||||
add(s, "No stack traceback available")
|
||||
add(s, stackTraceNewLine)
|
||||
add(s, "No stack traceback available\n")
|
||||
|
||||
proc quitOrDebug() {.inline.} =
|
||||
when not defined(endb):
|
||||
|
|
@ -214,13 +200,16 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
|||
if excHandler != nil:
|
||||
pushCurrentException(e)
|
||||
c_longjmp(excHandler.context, 1)
|
||||
elif e[] is EOutOfMemory:
|
||||
writeToStdErr(ename)
|
||||
quitOrDebug()
|
||||
else:
|
||||
if not isNil(buf):
|
||||
setLen(buf, 0)
|
||||
when hasSomeStackTrace:
|
||||
var buf = newStringOfCap(2000)
|
||||
rawWriteStackTrace(buf)
|
||||
if e.msg != nil and e.msg[0] != '\0':
|
||||
if not isNil(e.msg):
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
add(buf, $e.msg)
|
||||
add(buf, e.msg)
|
||||
else:
|
||||
add(buf, "Error: unhandled exception")
|
||||
add(buf, " [")
|
||||
|
|
@ -228,7 +217,21 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
|||
add(buf, "]\n")
|
||||
writeToStdErr(buf)
|
||||
else:
|
||||
writeToStdErr(ename)
|
||||
# ugly, but avoids heap allocations :-)
|
||||
template xadd(buf, s, slen: expr) =
|
||||
if L + slen < high(buf):
|
||||
copyMem(addr(buf[L]), cstring(s), slen)
|
||||
inc L, slen
|
||||
template add(buf, s: expr) =
|
||||
xadd(buf, s, s.len)
|
||||
var buf: array [0..2000, char]
|
||||
var L = 0
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
if not isNil(e.msg): add(buf, e.msg)
|
||||
add(buf, " [")
|
||||
xadd(buf, ename, c_strlen(ename))
|
||||
add(buf, "]\n")
|
||||
writeToStdErr(buf)
|
||||
quitOrDebug()
|
||||
GC_enable()
|
||||
|
||||
|
|
@ -240,54 +243,57 @@ proc reraiseException() {.compilerRtl.} =
|
|||
|
||||
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
|
||||
if not cond:
|
||||
#c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
||||
#quit(1)
|
||||
GC_disable() # BUGFIX: `$` allocates a new string object!
|
||||
if not isNil(assertBuf):
|
||||
# BUGFIX: when debugging the GC, assertBuf may be nil
|
||||
setLen(assertBuf, 0)
|
||||
add(assertBuf, "[Assertion failure] file: ")
|
||||
add(assertBuf, file)
|
||||
add(assertBuf, " line: ")
|
||||
add(assertBuf, $line)
|
||||
add(assertBuf, "\n")
|
||||
gAssertionFailed.msg = assertBuf
|
||||
GC_enable()
|
||||
if gAssertionFailed != nil:
|
||||
raise gAssertionFailed
|
||||
else:
|
||||
c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
||||
quit(1)
|
||||
var gAssertionFailed: ref EAssertionFailed
|
||||
new(gAssertionFailed)
|
||||
gAssertionFailed.msg = newStringOfCap(200)
|
||||
add(gAssertionFailed.msg, "[Assertion failure] file: ")
|
||||
add(gAssertionFailed.msg, file)
|
||||
add(gAssertionFailed.msg, " line: ")
|
||||
add(gAssertionFailed.msg, $line)
|
||||
add(gAssertionFailed.msg, "\n")
|
||||
raise gAssertionFailed
|
||||
|
||||
proc WriteStackTrace() =
|
||||
var s = ""
|
||||
rawWriteStackTrace(s)
|
||||
writeToStdErr(s)
|
||||
when hasSomeStackTrace:
|
||||
var s = ""
|
||||
rawWriteStackTrace(s)
|
||||
writeToStdErr(s)
|
||||
else:
|
||||
writeToStdErr("No stack traceback available\n")
|
||||
|
||||
var
|
||||
dbgAborting: bool # whether the debugger wants to abort
|
||||
when defined(endb):
|
||||
var
|
||||
dbgAborting: bool # whether the debugger wants to abort
|
||||
|
||||
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
||||
# print stack trace and quit
|
||||
var s = sig
|
||||
GC_disable()
|
||||
setLen(buf, 0)
|
||||
rawWriteStackTrace(buf)
|
||||
template processSignal(s, action: expr) =
|
||||
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
|
||||
elif s == SIGSEGV:
|
||||
action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
elif s == SIGABRT:
|
||||
when defined(endb):
|
||||
if dbgAborting: return # the debugger wants to abort
|
||||
action("SIGABRT: Abnormal termination.\n")
|
||||
elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
|
||||
elif s == SIGILL: action("SIGILL: Illegal operation.\n")
|
||||
elif s == SIGBUS:
|
||||
action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
else: action("unknown signal\n")
|
||||
|
||||
if s == SIGINT: add(buf, "SIGINT: Interrupted by Ctrl-C.\n")
|
||||
elif s == SIGSEGV:
|
||||
add(buf, "SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
elif s == SIGABRT:
|
||||
if dbgAborting: return # the debugger wants to abort
|
||||
add(buf, "SIGABRT: Abnormal termination.\n")
|
||||
elif s == SIGFPE: add(buf, "SIGFPE: Arithmetic error.\n")
|
||||
elif s == SIGILL: add(buf, "SIGILL: Illegal operation.\n")
|
||||
elif s == SIGBUS:
|
||||
add(buf, "SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
else: add(buf, "unknown signal\n")
|
||||
writeToStdErr(buf)
|
||||
dbgAborting = True # play safe here...
|
||||
GC_enable()
|
||||
# print stack trace and quit
|
||||
when hasSomeStackTrace:
|
||||
GC_disable()
|
||||
var buf = newStringOfCap(2000)
|
||||
rawWriteStackTrace(buf)
|
||||
processSignal(sig, buf.add) # nice hu? currying a la nimrod :-)
|
||||
writeToStdErr(buf)
|
||||
GC_enable()
|
||||
else:
|
||||
var msg: cstring
|
||||
template asgn(y: expr) = msg = y
|
||||
processSignal(sig, asgn)
|
||||
writeToStdErr(msg)
|
||||
when defined(endb): dbgAborting = True
|
||||
quit(1) # always quit when SIGABRT
|
||||
|
||||
proc registerSignalHandler() =
|
||||
|
|
|
|||
|
|
@ -279,7 +279,6 @@ proc initGC() =
|
|||
init(gch.tempStack)
|
||||
Init(gch.cycleRoots)
|
||||
Init(gch.decStack)
|
||||
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
|
||||
|
||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
||||
var d = cast[TAddress](dest)
|
||||
|
|
|
|||
|
|
@ -52,15 +52,10 @@ const
|
|||
IntShift = 5 + ord(sizeof(int) == 8) # 5 or 6, depending on int width
|
||||
IntMask = 1 shl IntShift - 1
|
||||
|
||||
var
|
||||
gOutOfMem: ref EOutOfMemory
|
||||
|
||||
proc raiseOutOfMem() {.noreturn.} =
|
||||
if gOutOfMem == nil:
|
||||
echo("out of memory; cannot even throw an exception")
|
||||
quit(1)
|
||||
gOutOfMem.msg = "out of memory"
|
||||
raise gOutOfMem
|
||||
proc raiseOutOfMem() {.noinline.} =
|
||||
if outOfMemHook != nil: outOfMemHook()
|
||||
echo("out of memory")
|
||||
quit(1)
|
||||
|
||||
when defined(boehmgc):
|
||||
when defined(windows):
|
||||
|
|
|
|||
|
|
@ -39,11 +39,24 @@ proc rawNewString(space: int): NimString {.compilerProc.} =
|
|||
(s+1) * sizeof(char)))
|
||||
result.space = s
|
||||
|
||||
proc mnewString(len: int): NimString {.exportc.} =
|
||||
#c_fprintf(c_stdout, "[NEWSTRING] len: %ld\n", len)
|
||||
proc mnewString(len: int): NimString {.compilerProc.} =
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
|
||||
proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
|
||||
var start = max(start, 0)
|
||||
var len = min(last, s.len-1) - start + 1
|
||||
if len > 0:
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
|
||||
result.data[len] = '\0'
|
||||
else:
|
||||
result = mnewString(0)
|
||||
|
||||
proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
|
||||
result = copyStrLast(s, start, s.len-1)
|
||||
|
||||
proc toNimStr(str: CString, len: int): NimString {.compilerProc.} =
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
|
|
@ -72,20 +85,6 @@ proc hashString(s: string): int {.compilerproc.} =
|
|||
h = h +% h shl 15
|
||||
result = h
|
||||
|
||||
proc copyStrLast(s: NimString, start, last: int): NimString {.exportc.} =
|
||||
var start = max(start, 0)
|
||||
var len = min(last, s.len-1) - start + 1
|
||||
if len > 0:
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
|
||||
result.data[len] = '\0'
|
||||
else:
|
||||
result = mnewString(0)
|
||||
|
||||
proc copyStr(s: NimString, start: int): NimString {.exportc.} =
|
||||
result = copyStrLast(s, start, s.len-1)
|
||||
|
||||
proc addChar(s: NimString, c: char): NimString =
|
||||
# is compilerproc!
|
||||
result = s
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@ proc ThreadVarsAlloc(size: int): pointer =
|
|||
result = c_malloc(size)
|
||||
zeroMem(result, size)
|
||||
proc ThreadVarsDealloc(p: pointer) {.importc: "free", nodecl.}
|
||||
proc initGlobals()
|
||||
|
||||
type
|
||||
PGcThread = ptr TGcThread
|
||||
|
|
@ -239,8 +238,7 @@ when not defined(useNimRtl):
|
|||
|
||||
initStackBottom()
|
||||
initGC()
|
||||
initGlobals()
|
||||
|
||||
|
||||
var heapLock: TSysLock
|
||||
InitSysLock(HeapLock)
|
||||
|
||||
|
|
@ -301,7 +299,6 @@ template ThreadProcWrapperBody(closure: expr) =
|
|||
setStackBottom(addr(t))
|
||||
initGC()
|
||||
t.stackBottom = addr(t)
|
||||
initGlobals()
|
||||
registerThread(t)
|
||||
try:
|
||||
t.fn(t.data)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue