diff options
Diffstat (limited to 'lib/core/runtime_v2.nim')
-rw-r--r-- | lib/core/runtime_v2.nim | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/core/runtime_v2.nim b/lib/core/runtime_v2.nim new file mode 100644 index 000000000..8a9068c37 --- /dev/null +++ b/lib/core/runtime_v2.nim @@ -0,0 +1,78 @@ +#[ +In this new runtime we simply the object layouts a bit: The runtime type +information is only accessed for the objects that have it and it's always +at offset 0 then. The ``ref`` object header is independent from the +runtime type and only contains a reference count. + +Object subtyping is checked via the generated 'name'. This should have +comparable overhead to the old pointer chasing approach but has the benefit +that it works across DLL boundaries. + +The generated name is a concatenation of the object names in the hierarchy +so that a subtype check becomes a substring check. For example:: + + type + ObjectA = object of RootObj + ObjectB = object of ObjectA + +ObjectA's ``name`` is "|ObjectA|RootObj|". +ObjectB's ``name`` is "|ObjectB|ObjectA|RootObj|". + +Now to check for ``x of ObjectB`` we need to check +for ``x.typ.name.hasSubstring("|ObjectB|")``. In the actual implementation, +however, we could also use a +hash of ``package & "." & module & "." & name`` to save space. + +]# + +type + TNimNode {.compilerProc.} = object # to keep the code generator simple + TNimType {.compilerProc.} = object + destructor: proc (p: pointer) {.nimcall, benign.} + size: int + name: cstring + PNimType = ptr TNimType + + ObjHeader = object + rc: int # the object header is now a single RC field. + # we could remove it in non-debug builds but this seems + # unwise. + +proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} = + proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.} + + result = strstr(obj.name, subclass) != nil + +proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} = + # checks if obj is of type subclass: + if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion") + +template `+!`(p: pointer, s: int): pointer = + cast[pointer](cast[int](p) +% s) + +template `-!`(p: pointer, s: int): pointer = + cast[pointer](cast[int](p) -% s) + +template head(p: pointer): ptr ObjHeader = + cast[ptr ObjHeader](cast[int](p) -% sizeof(ObjHeader)) + +proc nimNewObj(size: int): pointer {.compilerRtl.} = + result = alloc0(size + sizeof(ObjHeader)) +! sizeof(ObjHeader) + # XXX Respect defined(useMalloc) here! + +proc nimDecWeakRef(p: pointer) {.compilerRtl.} = + dec head(p).rc + +proc nimIncWeakRef(p: pointer) {.compilerRtl.} = + inc head(p).rc + +proc nimRawDispose(p: pointer) {.compilerRtl.} = + if head(p).rc != 0: + cstderr.rawWrite "[FATAL] dangling references exist\n" + quit 1 + dealloc(p -! sizeof(ObjHeader)) + +proc nimDestroyAndDispose(p: pointer) {.compilerRtl.} = + let d = cast[ptr PNimType](p)[].destructor + if d != nil: d(p) + nimRawDispose(p) |