threading code deactivated; tiny C bugfix: don't report warnings to error callback

This commit is contained in:
Araq 2010-09-19 21:35:44 +02:00
commit 93b3c03dbd
15 changed files with 208 additions and 135 deletions

View file

@ -1,14 +1,13 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Declaration of the Document Object Model for the ECMAScript backend.
## (c) 2008 Andreas Rumpf
when not defined(ecmascript):
{.error: "This module only works on the ECMAScript platform".}

View file

@ -1605,10 +1605,8 @@ when not defined(EcmaScript) and not defined(NimrodVM):
## can be used to mark a condition to be unlikely. This is a hint for the
## optimizer.
elif defined(ecmaScript):
include "system/ecmasys"
elif defined(NimrodVM):
# Stubs for the GC interface:
elif defined(ecmaScript) or defined(NimrodVM):
# Stubs:
proc GC_disable() = nil
proc GC_enable() = nil
proc GC_fullCollect() = nil
@ -1620,16 +1618,19 @@ elif defined(NimrodVM):
proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1
proc cmp(x, y: string): int =
if x == y: return 0
if x < y: return -1
return 1
proc dealloc(p: pointer) = nil
proc alloc(size: int): pointer = nil
proc alloc0(size: int): pointer = nil
proc realloc(p: Pointer, newsize: int): pointer = nil
when defined(ecmaScript):
include "system/ecmasys"
elif defined(NimrodVM):
proc cmp(x, y: string): int =
if x == y: return 0
if x < y: return -1
return 1
{.pop.} # checks
{.pop.} # hints

View file

@ -1,26 +1,12 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Stubs for the GC interface:
proc GC_disable() = nil
proc GC_enable() = nil
proc GC_fullCollect() = nil
proc GC_setStrategy(strategy: TGC_Strategy) = nil
proc GC_enableMarkAndSweep() = nil
proc GC_disableMarkAndSweep() = nil
proc GC_getStatistics(): string = return ""
proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1
proc alert(s: cstring) {.importc, nodecl.}
type
@ -130,8 +116,6 @@ proc raiseIndexError() {.compilerproc, noreturn.} =
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
raise newException(EInvalidField, f & " is not accessible")
proc SetConstr() {.varargs, pure, compilerproc.} =
asm """
var result = {};
@ -317,61 +301,58 @@ proc ewriteln(x: cstring) =
else:
raise newException(EInvalidValue, "<body> element does not exist yet!")
proc echo*(x: int) = ewriteln($x)
proc echo*(x: float) = ewriteln($x)
proc echo*(x: bool) = ewriteln(if x: cstring("true") else: cstring("false"))
proc echo*(x: string) = ewriteln(x)
proc echo*(x: cstring) = ewriteln(x)
proc echo[Ty](x: Ty) =
echo(x)
proc echo[Ty](x: openArray[Ty]) =
for a in items(x): echo(a)
proc rawEcho {.compilerproc.} =
var node = document.getElementsByTagName("body")[0]
if node == nil: raise newException(EIO, "<body> element does not exist yet!")
asm """
for (var i = 0; i < arguments.length; ++i) {
var x = `toEcmaStr`(arguments[i]);
`node`.appendChild(document.createTextNode(x))
}
"""
node.appendChild(document.createElement("br"))
# Arithmetic:
proc addInt(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` + `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow();
if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result;
"""
proc subInt(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` - `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow();
if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result;
"""
proc mulInt(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` * `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow();
if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result;
"""
proc divInt(a, b: int): int {.pure, compilerproc.} =
asm """
if (`b` == 0) raiseDivByZero();
if (`b` == -1 && `a` == 2147483647) raiseOverflow();
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
return Math.floor(`a` / `b`);
"""
proc modInt(a, b: int): int {.pure, compilerproc.} =
asm """
if (`b` == 0) raiseDivByZero();
if (`b` == -1 && `a` == 2147483647) raiseOverflow();
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
return Math.floor(`a` % `b`);
"""
proc addInt64(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` + `b`;
if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow();
|| result < -9223372036854775808) `raiseOverflow`();
return result;
"""
@ -379,7 +360,7 @@ proc subInt64(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` - `b`;
if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow();
|| result < -9223372036854775808) `raiseOverflow`();
return result;
"""
@ -387,21 +368,21 @@ proc mulInt64(a, b: int): int {.pure, compilerproc.} =
asm """
var result = `a` * `b`;
if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow();
|| result < -9223372036854775808) `raiseOverflow`();
return result;
"""
proc divInt64(a, b: int): int {.pure, compilerproc.} =
asm """
if (`b` == 0) raiseDivByZero();
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.floor(`a` / `b`);
"""
proc modInt64(a, b: int): int {.pure, compilerproc.} =
asm """
if (`b` == 0) raiseDivByZero();
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.floor(`a` % `b`);
"""
@ -415,13 +396,13 @@ proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`"""
raise e
include hti
include "system/hti"
proc isFatPointer(ti: PNimType): bool =
# This has to be consistent with the code generator!
return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject,
return ti.base.kind notin {tyObject,
tyArray, tyArrayConstr, tyPureObject, tyTuple,
tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr}
tyOpenArray, tySet, tyVar, tyRef, tyPtr}
proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
@ -452,7 +433,7 @@ proc NimCopy(x: pointer, ti: PNimType): pointer =
`result`[0] = `x`[0];
`result`[1] = `x`[1];
"""
of tyEmptySet, tySet:
of tySet:
asm """
`result` = {};
for (var key in `x`) { `result`[key] = `x`[key]; }

View file

@ -10,6 +10,10 @@
# Exception handling code. This is difficult because it has
# to work if there is no more memory (but it doesn't yet!).
var
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
## for CGI applications
when not defined(windows) or not defined(guiapp):
proc writeToStdErr(msg: CString) = write(stdout, msg)
@ -32,7 +36,7 @@ type
TSafePoint {.compilerproc, final.} = object
prev: PSafePoint # points to next safe point ON THE STACK
status: int
exc: ref E_Base # XXX only needed for bootstrapping
exc: ref E_Base # XXX only needed for bootstrapping; unused
context: C_JmpBuf
var
@ -55,6 +59,58 @@ proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
proc popCurrentException {.compilerRtl, inl.} =
currException = currException.parent
# some platforms have native support for stack traces:
const
nimrodStackTrace = compileOption("stacktrace")
nativeStackTrace = (defined(macosx) or defined(linux)) and
not nimrodStackTrace and false
# `nativeStackTrace` does not work for me --> deactivated for now. Maybe for
# the next release version.
when nativeStacktrace:
type
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
final, pure.} = object
dli_fname: CString
dli_fbase: pointer
dli_sname: CString
dli_saddr: pointer
proc backtrace(symbols: ptr pointer, size: int): int {.
importc: "backtrace", header: "<execinfo.h>".}
proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
importc: "dladdr", header: "<dlfcn.h>".}
var
tempAddresses: array [0..127, pointer] # cannot be allocated on the stack!
tempDlInfo: TDl_info
proc auxWriteStackTraceWithBacktrace(s: var string) =
# This is allowed to be expensive since it only happens during crashes
# (but this way you don't need manual stack tracing)
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
len(tempAddresses))
var enabled = false
for i in 0..size-1:
var dlresult = dladdr(tempAddresses[i], addr(tempDlInfo))
if enabled:
if dlresult != 0:
var oldLen = s.len
add(s, tempDlInfo.dli_fname)
if tempDlInfo.dli_sname != nil:
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
add(s, tempDlInfo.dli_sname)
else:
add(s, '?')
add(s, stackTraceNewLine)
else:
if dlresult != 0 and tempDlInfo.dli_sname != nil and
c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32:
# Once we're past signalHandler, we're at what the user is
# interested in
enabled = true
type
PFrame = ptr TFrame
TFrame {.importc, nodecl, final.} = object
@ -74,9 +130,6 @@ var
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
## for CGI applications
proc auxWriteStackTrace(f: PFrame, s: var string) =
const
firstCalls = 32
@ -120,7 +173,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
add(s, stackTraceNewLine)
proc rawWriteStackTrace(s: var string) =
when compileOption("stacktrace") or compileOption("linetrace"):
when nimrodStackTrace:
if framePtr == nil:
add(s, "No stack traceback available")
add(s, stackTraceNewLine)
@ -128,6 +181,10 @@ proc rawWriteStackTrace(s: var string) =
add(s, "Traceback (most recent call last)")
add(s, stackTraceNewLine)
auxWriteStackTrace(framePtr, s)
elif nativeStackTrace:
add(s, "Traceback from system (most recent call last)")
add(s, stackTraceNewLine)
auxWriteStackTraceWithBacktrace(s)
else:
add(s, "No stack traceback available")
add(s, stackTraceNewLine)
@ -197,11 +254,6 @@ proc WriteStackTrace() =
rawWriteStackTrace(s)
writeToStdErr(s)
#proc stackTraceWrapper {.noconv.} =
# writeStackTrace()
#addQuitProc(stackTraceWrapper)
var
dbgAborting: bool # whether the debugger wants to abort

View file

@ -77,14 +77,16 @@ var
# collection, not a lock for threads!
proc lock(gch: var TGcHeap) {.inline.} =
if isMultiThreaded:
Lock(gch.zctLock)
lock(gch.cycleRootsLock)
when hasThreadSupport:
if isMultiThreaded:
Lock(gch.zctLock)
lock(gch.cycleRootsLock)
proc unlock(gch: var TGcHeap) {.inline.} =
if isMultiThreaded:
unlock(gch.zctLock)
unlock(gch.cycleRootsLock)
when hasThreadSupport:
if isMultiThreaded:
unlock(gch.zctLock)
unlock(gch.cycleRootsLock)
proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
if (c.refcount and rcZct) == 0:
@ -202,15 +204,19 @@ proc prepareDealloc(cell: PCell) =
proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
# we MUST access gch as a global here, because this crosses DLL boundaries!
if isMultiThreaded: Lock(gch.cycleRootsLock)
when hasThreadSupport:
if isMultiThreaded: Lock(gch.cycleRootsLock)
incl(gch.cycleRoots, c)
if isMultiThreaded: Unlock(gch.cycleRootsLock)
when hasThreadSupport:
if isMultiThreaded: Unlock(gch.cycleRootsLock)
proc rtlAddZCT(c: PCell) {.rtl, inl.} =
# we MUST access gch as a global here, because this crosses DLL boundaries!
if isMultiThreaded: Lock(gch.zctLock)
when hasThreadSupport:
if isMultiThreaded: Lock(gch.zctLock)
addZCT(gch.zct, c)
if isMultiThreaded: Unlock(gch.zctLock)
when hasThreadSupport:
if isMultiThreaded: Unlock(gch.zctLock)
proc decRef(c: PCell) {.inline.} =
when stressGC:
@ -480,7 +486,7 @@ proc gcMark(p: pointer) {.inline.} =
add(gch.decStack, cell)
proc markThreadStacks(gch: var TGcHeap) =
when isMultiThreaded:
when hasThreadSupport:
nil
# ----------------- stack management --------------------------------------

View file

@ -7,12 +7,17 @@
# distribution, for details about the copyright.
#
when defined(gcc) or defined(llvm_gcc):
const
hasThreadSupport = false # deactivate for now: thread stack walking
# is missing!
maxThreads = 256
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
proc sync_add_and_fetch(p: var int, val: int): int {.
importc: "__sync_add_and_fetch", nodecl.}
proc sync_sub_and_fetch(p: var int, val: int): int {.
importc: "__sync_sub_and_fetch", nodecl.}
elif defined(vcc):
elif defined(vcc) and hasThreadSupport:
proc sync_add_and_fetch(p: var int, val: int): int {.
importc: "NimXadd", nodecl.}
else:
@ -20,19 +25,18 @@ else:
inc(p, val)
result = p
const
isMultiThreaded* = true
maxThreads = 256
var
isMultiThreaded: bool # true when prog created at least 1 thread
proc atomicInc(memLoc: var int, x: int): int =
when isMultiThreaded:
when hasThreadSupport:
result = sync_add_and_fetch(memLoc, x)
else:
inc(memLoc, x)
result = memLoc
proc atomicDec(memLoc: var int, x: int): int =
when isMultiThreaded:
when hasThreadSupport:
when defined(sync_sub_and_fetch):
result = sync_sub_and_fetch(memLoc, x)
else:
@ -85,11 +89,8 @@ type
TThreadFunc* = proc (closure: pointer) {.cdecl.}
proc createThread*(t: var TThread, fn: TThreadFunc) =
nil
proc destroyThread*(t: var TThread) =
nil