Skip to content

Commit 9354896

Browse files
committed
ok
1 parent a7db22d commit 9354896

File tree

4 files changed

+133
-37
lines changed

4 files changed

+133
-37
lines changed

compiler/closureiters.nim

Lines changed: 127 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ type
153153
body: PNode
154154
excLandingState: PNode # label of exception landing state (except or finally)
155155
inlinable: bool
156+
deletable: bool
156157

157158
Ctx = object
158159
g: ModuleGraph
@@ -162,6 +163,7 @@ type
162163
curExcLevelSym: PSym # Current exception
163164

164165
# states: seq[tuple[label: PNode, body: PNode, inlinable: bool]] # The resulting states. Label is int literal.
166+
uninlinableStates: seq[PNode] # List of state labels that must not be inlined
165167
states: seq[State] # The resulting states. Label is int literal.
166168
finallyPathStack: seq[FinallyTarget] # nkWhileStmt, nkBlock, nkTryStmt
167169
stateLoopLabel: PSym # Label to break on, when jumping between states.
@@ -254,7 +256,7 @@ proc newCurExcLevelAccess(ctx: var Ctx): PNode =
254256
proc newStateLabel(ctx: Ctx): PNode =
255257
ctx.g.newIntLit(TLineInfo(), 0)
256258

257-
proc newState1(ctx: var Ctx, n: PNode, inlinable: bool, label: PNode): PNode =
259+
proc newState(ctx: var Ctx, n: PNode, inlinable: bool, label: PNode): PNode =
258260
# Creates a new state, adds it to the context
259261
# Returns label of the newly created state
260262

@@ -896,6 +898,8 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
896898
# :state = :env.finallyPath[curFinallyLevel_const]
897899

898900
let nextState = ctx.newFinallyPathAccess(ctx.curFinallyLevel, info)
901+
let exitFinally = newTree(nkGotoState, nextState)
902+
899903
let cmpStateToZero = newTreeIT(nkCall,
900904
info, ctx.g.getSysType(info, tyBool),
901905
newSymNode(ctx.g.getSysMagic(info, "==", mEqI), info),
@@ -921,7 +925,6 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
921925
newTree(nkReturnStmt, retValue)
922926
retStmt.flags.incl(nfNoRewrite)
923927

924-
let exitFinally = newTree(nkGotoState, nextState)
925928

926929
let ifBody = newTree(nkIfStmt,
927930
newTree(nkElifBranch, excNilCmp, retStmt),
@@ -932,7 +935,8 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
932935

933936
result = newTree(nkIfStmt,
934937
newTreeI(nkElifBranch, info, cmpStateToZero, ifBody),
935-
newTreeI(nkElse, info, exitFinally))
938+
# newTreeI(nkElse, info, exitFinally)
939+
)
936940

937941

938942
proc newJumpAlongFinallyChain(ctx: var Ctx, finallyChain: seq[PNode], info: TLineInfo): PNode =
@@ -975,9 +979,10 @@ proc transformBreakStmt(ctx: var Ctx, n: PNode): PNode =
975979
elif b.kind == nkFinally:
976980
finallyChain.add(ctx.finallyPathStack[i].enterLabel)
977981

978-
assert(finallyChain.len > 0)
979-
980-
result = ctx.newJumpAlongFinallyChain(finallyChain, n.info)
982+
if finallyChain.len > 0:
983+
result = ctx.newJumpAlongFinallyChain(finallyChain, n.info)
984+
else:
985+
result = n
981986

982987
proc transformContinueStmt(ctx: var Ctx, n: PNode): PNode =
983988
# "Continuing" involves finding the corresponding target state in finallyPathStack,
@@ -1072,17 +1077,18 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
10721077
s.add(n[j])
10731078

10741079
n.sons.setLen(i + 1)
1075-
discard ctx.newState1(s, true, label)
1080+
discard ctx.newState(s, true, label)
10761081
if ctx.transformClosureIteratorBody(s, gotoOut) != s:
10771082
internalError(ctx.g.config, "transformClosureIteratorBody != s")
10781083
break
10791084
else:
10801085
n[i] = ctx.transformBreaksContinuesAndReturns(n[i])
10811086

10821087
of nkYieldStmt:
1083-
result = newNodeI(nkStmtList, n.info)
1084-
result.add(n)
1085-
result.add(gotoOut)
1088+
result = addGotoOut(result, gotoOut)
1089+
# result = newNodeI(nkStmtList, n.info)
1090+
# result.add(n)
1091+
# result.add(gotoOut)
10861092

10871093
of nkElse, nkElseExpr:
10881094
result[0] = addGotoOut(result[0], gotoOut)
@@ -1115,7 +1121,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
11151121
# result = newNodeI(nkGotoState, n.info)
11161122

11171123
let s = newNodeI(nkStmtList, n.info)
1118-
let enterLabel = ctx.newState1(s, false, nil)
1124+
let enterLabel = ctx.newState(s, false, nil)
11191125

11201126
let ifNode = newNodeI(nkIfStmt, n.info)
11211127
let elifBranch = newNodeI(nkElifBranch, n.info)
@@ -1190,7 +1196,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
11901196
elif finallyBody.kind != nkEmpty: finallyLabel
11911197
else: oldExcLandingState
11921198
# ctx.curExcHandlingState = exceptIdx
1193-
discard ctx.newState1(tryBody, false, tryLabel)
1199+
discard ctx.newState(tryBody, false, tryLabel)
11941200
# assert(realTryIdx.intVal == tryIdx)
11951201

11961202
if finallyBody.kind != nkEmpty:
@@ -1203,7 +1209,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
12031209
if exceptBody.kind != nkEmpty:
12041210
ctx.curExcLandingState = if finallyBody.kind != nkEmpty: finallyLabel
12051211
else: oldExcLandingState
1206-
discard ctx.newState1(exceptBody, false, exceptLabel)
1212+
discard ctx.newState(exceptBody, false, exceptLabel)
12071213
# assert(realExceptIdx.intVal == -exceptIdx)
12081214

12091215
let normalOut = if finallyBody.kind != nkEmpty: gotoOut else: nil
@@ -1216,8 +1222,9 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
12161222

12171223
if finallyBody.kind != nkEmpty:
12181224
discard ctx.finallyPathStack.pop()
1219-
discard ctx.newState1(finallyBody, false, finallyLabel)
1220-
if ctx.transformClosureIteratorBody(finallyBody, gotoOut) != finallyBody:
1225+
discard ctx.newState(finallyBody, false, finallyLabel)
1226+
let finallyExit = newTree(nkGotoState, ctx.newFinallyPathAccess(ctx.curFinallyLevel - 1, finallyBody.info))
1227+
if ctx.transformClosureIteratorBody(finallyBody, finallyExit) != finallyBody:
12211228
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
12221229
dec ctx.curFinallyLevel
12231230

@@ -1490,27 +1497,119 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
14901497
blockStmt.add(blockBody)
14911498
loopBody.add(blockStmt)
14921499

1493-
proc countStateOccurences(n: PNode, stateOccurences: var openArray[int]) =
1500+
proc countStateOccurences(ctx: var Ctx, n: PNode, stateOccurences: var openArray[int]) =
14941501
## Find all nkGotoState(stateIdx) nodes that do not follow nkYield.
14951502
## For every such node increment stateOccurences[stateIdx]
14961503
for i, c in n:
1497-
if c.kind == nkGotoState and (i == 0 or n[i - 1].kind != nkYieldStmt):
1504+
if c.kind == nkGotoState and c[0].kind == nkIntLit and (i > 0 and n[i - 1].kind != nkYieldStmt):
14981505
let stateIdx = c[0].intVal
14991506
if stateIdx >= 0:
15001507
inc stateOccurences[stateIdx]
1508+
elif c.kind == nkIntLit:
1509+
let idx = c.intVal
1510+
if idx >= 0 and idx < ctx.states.len and ctx.states[idx].label == c:
1511+
ctx.states[idx].inlinable = false
15011512
else:
1502-
countStateOccurences(c, stateOccurences)
1513+
ctx.countStateOccurences(c, stateOccurences)
1514+
1515+
proc replaceDeletedStates(ctx: var Ctx, n: PNode): PNode =
1516+
result = n
1517+
for i in 0 ..< n.safeLen:
1518+
let c = n[i]
1519+
if c.kind == nkIntLit:
1520+
let idx = c.intVal
1521+
if idx >= 0 and idx < ctx.states.len and ctx.states[idx].label == c and ctx.states[idx].deletable:
1522+
let ns = ctx.replaceDeletedStates(ctx.states[idx].body)
1523+
assert(ns.kind == nkStmtList and ns.len == 1 and ns[0].kind == nkGotoState and ns[0][0].kind == nkIntLit)
1524+
n[i] = ns[0][0]
1525+
else:
1526+
n[i] = ctx.replaceDeletedStates(c)
1527+
1528+
proc replaceInlinedStates(ctx: var Ctx, n: PNode): PNode =
1529+
## Find all nkGotoState(stateIdx) nodes that do not follow nkYield.
1530+
## For every such node increment stateOccurences[stateIdx]
1531+
result = n
1532+
for i in 0 ..< n.safeLen:
1533+
let c = n[i]
1534+
if c.kind == nkGotoState and c[0].kind == nkIntLit and (i > 0 and n[i - 1].kind != nkYieldStmt):
1535+
let stateIdx = c[0].intVal
1536+
if stateIdx >= 0:
1537+
if ctx.states[stateIdx].inlinable:
1538+
n[i] = ctx.states[stateIdx].body
1539+
else:
1540+
n[i] = ctx.replaceInlinedStates(c)
1541+
15031542

15041543
proc deleteEmptyStates(ctx: var Ctx) =
1544+
# 1. Assign temporary indexes to state labels to facilitate
1545+
# countStateOccurences. Label number will correspond to index in
1546+
# ctx.states
1547+
1548+
# for i in 0 .. ctx.states.high:
1549+
# ctx.states[i].label.intVal = i
1550+
1551+
# 1. Delete empty states: go through ctx.states,
1552+
# if a state consists only of gotoState node, delete it from states
1553+
# and replace its label index to its target state
1554+
1555+
# var labelsToReplace = newSeq[(PNode, PNode, bool)]()
1556+
1557+
# Collect empty states
1558+
for i in 0 .. ctx.states.high:
1559+
let s = ctx.states[i]
1560+
let body = skipStmtList(s.body)
1561+
if body.kind == nkGotoState and body[0].kind == nkIntLit and body[0].intVal >= 0:
1562+
ctx.states[i].deletable = true
1563+
1564+
# Delete empty states
1565+
for i in 0 .. ctx.states.high:
1566+
ctx.states[i].body = ctx.replaceDeletedStates(ctx.states[i].body)
1567+
1568+
# Remove deletable states
1569+
var i = 0
1570+
while i < ctx.states.len:
1571+
if ctx.states[i].deletable:
1572+
ctx.states.delete(i)
1573+
else:
1574+
inc i
1575+
1576+
# Reassign state label indexes
1577+
for i in 0 .. ctx.states.high:
1578+
ctx.states[i].label.intVal = i
1579+
1580+
# 2. Count state occurences
15051581
var stateOccurences = newSeq[int](ctx.states.len)
15061582
for s in ctx.states:
1507-
countStateOccurences(s.body, stateOccurences)
1508-
echo "StateOccurences: ", stateOccurences
1583+
ctx.countStateOccurences(s.body, stateOccurences)
1584+
15091585
var statesToInline = newSeq[int]()
15101586
for i, o in stateOccurences:
15111587
if o == 1 and ctx.states[i].inlinable:
1512-
statesToInline.add(i)
1513-
echo "States to inline: ", statesToInline
1588+
discard
1589+
else:
1590+
ctx.states[i].inlinable = false
1591+
# statesToInline.add(i)
1592+
1593+
# echo "States to optimize:"
1594+
# for i, s in ctx.states:
1595+
# if s.deletable: echo i, ": delete"
1596+
# elif s.inlinable: echo i, ": inline"
1597+
1598+
# Inline states
1599+
for i in 0 .. ctx.states.high:
1600+
ctx.states[i].body = ctx.replaceInlinedStates(ctx.states[i].body)
1601+
1602+
# Remove inlined states
1603+
i = 0
1604+
while i < ctx.states.len:
1605+
if ctx.states[i].inlinable:
1606+
ctx.states.delete(i)
1607+
else:
1608+
inc i
1609+
1610+
# Reassign state label indexes
1611+
for i in 0 .. ctx.states.high:
1612+
ctx.states[i].label.intVal = i
15141613

15151614
# proc deleteEmptyStates(ctx: var Ctx) =
15161615
# let goOut = newTree(nkGotoState, ctx.g.newIntLit(TLineInfo(), -1))
@@ -1625,7 +1724,7 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
16251724
var n = n.toStmtList
16261725
# echo "transformed into ", n
16271726

1628-
discard ctx.newState1(n, false, nil)
1727+
discard ctx.newState(n, false, nil)
16291728
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))
16301729

16311730
var ns = false
@@ -1638,13 +1737,13 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
16381737
# Splitting transformation
16391738
discard ctx.transformClosureIteratorBody(n, gotoOut)
16401739

1641-
# Optimize empty states away
1642-
# ctx.deleteEmptyStates()
1643-
16441740
# Assign state label indexes
16451741
for i in 0 .. ctx.states.high:
16461742
ctx.states[i].label.intVal = i
16471743

1744+
# Optimize empty states away
1745+
ctx.deleteEmptyStates()
1746+
16481747
let caseDispatcher = newTreeI(nkCaseStmt, n.info,
16491748
ctx.newStateAccess())
16501749

@@ -1662,11 +1761,11 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
16621761
result = liftLocals(ctx, result)
16631762

16641763
when false:
1665-
echo "TRANSFORM TO STATES: "
1764+
echo "TRANSFORM TO STATES:"
16661765
echo renderTree(result)
16671766

16681767
# echo "exception table:"
16691768
# for i, s in ctx.states:
16701769
# echo i, " -> ", s.excLandingState
16711770

1672-
echo "ENV: ", renderTree(getEnvParam(fn).typ.elementType.n)
1771+
# echo "ENV: ", renderTree(getEnvParam(fn).typ.elementType.n)

lib/system/embedded.nim

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ proc writeStackTrace() = discard
5050
proc unsetControlCHook() = discard
5151
proc setControlCHook(hook: proc () {.noconv.}) = discard
5252

53-
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
54-
sysFatal(ReraiseDefect, "exception handling is not available")
55-
5653
when gotoBasedExceptions:
5754
var nimInErrorMode {.threadvar.}: bool
5855

lib/system/excpt.nim

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,9 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
461461
if globalRaiseHook != nil:
462462
if not globalRaiseHook(e): return
463463
when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
464-
if e == currException:
465-
{.emit: "throw;".}
466-
else:
464+
if e != currException:
467465
pushCurrentException(e)
468-
{.emit: "throw `e`;".}
466+
{.emit: "throw `e`;".}
469467
elif quirkyExceptions or gotoBasedExceptions:
470468
pushCurrentException(e)
471469
when gotoBasedExceptions:

lib/system/jssys.nim

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ proc getCurrentExceptionMsg*(): string =
7272
proc setCurrentException*(exc: ref Exception) =
7373
lastJSError = cast[PJSError](exc)
7474
75-
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
76-
## Used to set up exception handling for closure iterators
75+
proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inline.} =
76+
## Used to set up exception handling for closure iterators.
77+
78+
# XXX Shouldn't there be execption stack like in excpt.nim?
7779
setCurrentException(e)
7880
7981
proc auxWriteStackTrace(f: PCallFrame): string =

0 commit comments

Comments
 (0)