Skip to content

Commit 7800fa3

Browse files
Araqnarimiran
authored andcommitted
specialize genericReset (#14398)
* progress * make tests green * maybe we also want to reset pointers, dunno * progress * cleanup; fixes #13879 [backport:1.2] (cherry picked from commit b35d370)
1 parent bcfbaea commit 7800fa3

File tree

4 files changed

+124
-26
lines changed

4 files changed

+124
-26
lines changed

compiler/ccgexprs.nim

+23-23
Original file line numberDiff line numberDiff line change
@@ -1194,9 +1194,11 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
11941194
proc genReset(p: BProc, n: PNode) =
11951195
var a: TLoc
11961196
initLocExpr(p, n[1], a)
1197-
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
1198-
[addrLoc(p.config, a),
1199-
genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info)])
1197+
specializeReset(p, a)
1198+
when false:
1199+
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
1200+
[addrLoc(p.config, a),
1201+
genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info)])
12001202

12011203
proc genDefault(p: BProc; n: PNode; d: var TLoc) =
12021204
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
@@ -2787,6 +2789,21 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
27872789
else:
27882790
globalError(p.config, info, "cannot create null element for: " & $t.kind)
27892791

2792+
proc caseObjDefaultBranch(obj: PNode; branch: Int128): int =
2793+
for i in 1 ..< obj.len:
2794+
for j in 0 .. obj[i].len - 2:
2795+
if obj[i][j].kind == nkRange:
2796+
let x = getOrdValue(obj[i][j][0])
2797+
let y = getOrdValue(obj[i][j][1])
2798+
if branch >= x and branch <= y:
2799+
return i
2800+
elif getOrdValue(obj[i][j]) == branch:
2801+
return i
2802+
if obj[i].len == 1:
2803+
# else branch
2804+
return i
2805+
assert(false, "unreachable")
2806+
27902807
proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
27912808
result: var Rope; count: var int;
27922809
isConst: bool, info: TLineInfo) =
@@ -2809,31 +2826,14 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
28092826
branch = getOrdValue(constOrNil[i])
28102827
break
28112828

2812-
var selectedBranch = -1
2813-
block branchSelection:
2814-
for i in 1 ..< obj.len:
2815-
for j in 0 .. obj[i].len - 2:
2816-
if obj[i][j].kind == nkRange:
2817-
let x = getOrdValue(obj[i][j][0])
2818-
let y = getOrdValue(obj[i][j][1])
2819-
if branch >= x and branch <= y:
2820-
selectedBranch = i
2821-
break branchSelection
2822-
elif getOrdValue(obj[i][j]) == branch:
2823-
selectedBranch = i
2824-
break branchSelection
2825-
if obj[i].len == 1:
2826-
# else branch
2827-
selectedBranch = i
2828-
assert(selectedBranch >= 1)
2829-
2829+
let selectedBranch = caseObjDefaultBranch(obj, branch)
28302830
result.add "{"
28312831
var countB = 0
28322832
let b = lastSon(obj[selectedBranch])
28332833
# designated initilization is the only way to init non first element of unions
28342834
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
2835-
if b.kind == nkRecList and b.len > 0:
2836-
result.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {"
2835+
if b.kind == nkRecList and b.len > 0:
2836+
result.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {"
28372837
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
28382838
result.add "}"
28392839
elif b.kind == nkSym:

compiler/ccgreset.nim

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#
2+
#
3+
# The Nim Compiler
4+
# (c) Copyright 2020 Andreas Rumpf
5+
#
6+
# See the file "copying.txt", included in this
7+
# distribution, for details about the copyright.
8+
#
9+
10+
# included from cgen.nim
11+
12+
## Code specialization instead of the old, incredibly slow 'genericReset'
13+
## implementation.
14+
15+
proc specializeResetT(p: BProc, accessor: Rope, typ: PType)
16+
17+
proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
18+
typ: PType) =
19+
if n == nil: return
20+
case n.kind
21+
of nkRecList:
22+
for i in 0..<n.len:
23+
specializeResetN(p, accessor, n[i], typ)
24+
of nkRecCase:
25+
if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN")
26+
let disc = n[0].sym
27+
if disc.loc.r == nil: fillObjectFields(p.module, typ)
28+
if disc.loc.t == nil:
29+
internalError(p.config, n.info, "specializeResetN()")
30+
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
31+
for i in 1..<n.len:
32+
let branch = n[i]
33+
assert branch.kind in {nkOfBranch, nkElse}
34+
if branch.kind == nkOfBranch:
35+
genCaseRange(p, branch)
36+
else:
37+
lineF(p, cpsStmts, "default:$n", [])
38+
specializeResetN(p, accessor, lastSon(branch), typ)
39+
lineF(p, cpsStmts, "break;$n", [])
40+
lineF(p, cpsStmts, "} $n", [])
41+
specializeResetT(p, "$1.$2" % [accessor, disc.loc.r], disc.loc.t)
42+
of nkSym:
43+
let field = n.sym
44+
if field.typ.kind == tyVoid: return
45+
if field.loc.r == nil: fillObjectFields(p.module, typ)
46+
if field.loc.t == nil:
47+
internalError(p.config, n.info, "specializeResetN()")
48+
specializeResetT(p, "$1.$2" % [accessor, field.loc.r], field.loc.t)
49+
else: internalError(p.config, n.info, "specializeResetN()")
50+
51+
proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
52+
if typ == nil: return
53+
54+
case typ.kind
55+
of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred,
56+
tySink, tyOwned:
57+
specializeResetT(p, accessor, lastSon(typ))
58+
of tyArray:
59+
let arraySize = lengthOrd(p.config, typ[0])
60+
var i: TLoc
61+
getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i)
62+
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
63+
[i.r, arraySize])
64+
specializeResetT(p, ropecg(p.module, "$1[$2]", [accessor, i.r]), typ[1])
65+
lineF(p, cpsStmts, "}$n", [])
66+
of tyObject:
67+
for i in 0..<typ.len:
68+
var x = typ[i]
69+
if x != nil: x = x.skipTypes(skipPtrs)
70+
specializeResetT(p, accessor.parentObj(p.module), x)
71+
if typ.n != nil: specializeResetN(p, accessor, typ.n, typ)
72+
of tyTuple:
73+
let typ = getUniqueType(typ)
74+
for i in 0..<typ.len:
75+
specializeResetT(p, ropecg(p.module, "$1.Field$2", [accessor, i]), typ[i])
76+
77+
of tyString, tyRef, tySequence:
78+
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1, NIM_NIL);$n", [accessor])
79+
80+
of tyProc:
81+
if typ.callConv == ccClosure:
82+
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1.ClE_0, NIM_NIL);$n", [accessor])
83+
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
84+
else:
85+
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
86+
of tyChar, tyBool, tyEnum, tyInt..tyUInt64:
87+
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
88+
of tyCString, tyPointer, tyPtr, tyVar, tyLent:
89+
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
90+
else:
91+
discard
92+
93+
proc specializeReset(p: BProc, a: TLoc) =
94+
specializeResetT(p, rdLoc(a), a.t)

compiler/cgen.nim

+6-2
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ proc isComplexValueType(t: PType): bool {.inline.} =
390390
result = t.kind in {tyArray, tySet, tyTuple, tyObject} or
391391
(t.kind == tyProc and t.callConv == ccClosure)
392392

393+
include ccgreset
394+
393395
proc resetLoc(p: BProc, loc: var TLoc) =
394396
let containsGcRef = optSeqDestructors notin p.config.globalOptions and containsGarbageCollectedRef(loc.t)
395397
let typ = skipTypes(loc.t, abstractVarRange)
@@ -409,8 +411,10 @@ proc resetLoc(p: BProc, loc: var TLoc) =
409411
if optNilCheck in p.options:
410412
linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", [addrLoc(p.config, loc)])
411413
if loc.storage != OnStack and containsGcRef:
412-
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
413-
[addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)])
414+
specializeReset(p, loc)
415+
when false:
416+
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
417+
[addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)])
414418
# XXX: generated reset procs should not touch the m_type
415419
# field, so disabling this should be safe:
416420
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)

lib/system/gc_ms.nim

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
104104
# used for code generation concerning debugging
105105
result = usrToCell(c).typ
106106

107-
proc unsureAsgnRef(dest: PPointer, src: pointer) {.inline.} =
107+
proc unsureAsgnRef(dest: PPointer, src: pointer) {.inline, compilerproc.} =
108108
dest[] = src
109109

110110
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =

0 commit comments

Comments
 (0)