parent
f9d7e8db2a
commit
f16449ec22
5 changed files with 137 additions and 31 deletions
|
|
@ -438,7 +438,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
if regs[rc].intVal > high(int):
|
if regs[rc].intVal > high(int):
|
||||||
stackTrace(c, tos, pc, errIndexOutOfBounds)
|
stackTrace(c, tos, pc, errIndexOutOfBounds)
|
||||||
let idx = regs[rc].intVal.int
|
let idx = regs[rc].intVal.int
|
||||||
# XXX what if the array is not 0-based? -> codegen should insert a sub
|
|
||||||
let src = regs[rb].node
|
let src = regs[rb].node
|
||||||
if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
|
if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
|
||||||
regs[ra].node = src.sons[idx]
|
regs[ra].node = src.sons[idx]
|
||||||
|
|
@ -504,13 +503,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
else:
|
else:
|
||||||
stackTrace(c, tos, pc, errNilAccess)
|
stackTrace(c, tos, pc, errNilAccess)
|
||||||
of opcWrDeref:
|
of opcWrDeref:
|
||||||
# a[] = b
|
# a[] = c; b unused
|
||||||
let ra = instr.regA
|
let ra = instr.regA
|
||||||
let rb = instr.regB
|
let rc = instr.regC
|
||||||
case regs[ra].kind
|
case regs[ra].kind
|
||||||
of rkNodeAddr: putIntoNode(regs[ra].nodeAddr[], regs[rb])
|
of rkNodeAddr: putIntoNode(regs[ra].nodeAddr[], regs[rc])
|
||||||
of rkRegisterAddr: regs[ra].regAddr[] = regs[rb]
|
of rkRegisterAddr: regs[ra].regAddr[] = regs[rc]
|
||||||
of rkNode: putIntoNode(regs[ra].node, regs[rb])
|
of rkNode: putIntoNode(regs[ra].node, regs[rc])
|
||||||
else: stackTrace(c, tos, pc, errNilAccess)
|
else: stackTrace(c, tos, pc, errNilAccess)
|
||||||
of opcAddInt:
|
of opcAddInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
|
|
@ -751,11 +750,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
regs[ra].node.strVal.add getstr(regs[i])
|
regs[ra].node.strVal.add getstr(regs[i])
|
||||||
of opcAddStrCh:
|
of opcAddStrCh:
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
createStrKeepNode regs[ra]
|
#createStrKeepNode regs[ra]
|
||||||
regs[ra].node.strVal.add(regs[rb].intVal.chr)
|
regs[ra].node.strVal.add(regs[rb].intVal.chr)
|
||||||
of opcAddStrStr:
|
of opcAddStrStr:
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
createStrKeepNode regs[ra]
|
#createStrKeepNode regs[ra]
|
||||||
regs[ra].node.strVal.add(regs[rb].node.strVal)
|
regs[ra].node.strVal.add(regs[rb].node.strVal)
|
||||||
of opcAddSeqElem:
|
of opcAddSeqElem:
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
|
|
@ -992,7 +991,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
return TFullReg(kind: rkNone)
|
return TFullReg(kind: rkNone)
|
||||||
of opcSetLenStr:
|
of opcSetLenStr:
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
createStrKeepNode regs[ra]
|
#createStrKeepNode regs[ra]
|
||||||
regs[ra].node.strVal.setLen(regs[rb].intVal.int)
|
regs[ra].node.strVal.setLen(regs[rb].intVal.int)
|
||||||
of opcOf:
|
of opcOf:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@
|
||||||
# let s = a & b # no matter what, create fresh node
|
# let s = a & b # no matter what, create fresh node
|
||||||
# s = a & b # no matter what, keep the node
|
# s = a & b # no matter what, keep the node
|
||||||
#
|
#
|
||||||
|
# Also *stores* into non-temporary memory need to perform deep copies:
|
||||||
|
# a.b = x.y
|
||||||
|
# We used to generate opcAsgn for the *load* of 'x.y' but this is clearly
|
||||||
|
# wrong! We need to produce opcAsgn (the copy) for the *store*. This also
|
||||||
|
# solves the opcLdConst vs opcAsgnConst issue. Of course whether we need
|
||||||
|
# this copy depends on the involved types.
|
||||||
|
|
||||||
import
|
import
|
||||||
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||||
|
|
@ -531,12 +537,12 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
of nkDerefExpr, nkHiddenDeref:
|
of nkDerefExpr, nkHiddenDeref:
|
||||||
let dest = c.genx(le.sons[0], {gfAddrOf})
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
c.gABC(le, opcWrDeref, dest, value)
|
c.gABC(le, opcWrDeref, dest, 0, value)
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if le.sym.isGlobal:
|
if le.sym.isGlobal:
|
||||||
let dest = c.genx(le, {gfAddrOf})
|
let dest = c.genx(le, {gfAddrOf})
|
||||||
c.gABC(le, opcWrDeref, dest, value)
|
c.gABC(le, opcWrDeref, dest, 0, value)
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
@ -1097,6 +1103,25 @@ proc checkCanEval(c: PCtx; n: PNode) =
|
||||||
not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
|
not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
|
||||||
cannotEval(n)
|
cannotEval(n)
|
||||||
|
|
||||||
|
proc isTemp(c: PCtx; dest: TDest): bool =
|
||||||
|
result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
|
||||||
|
|
||||||
|
template needsAdditionalCopy(n): expr =
|
||||||
|
not c.isTemp(dest) and not fitsRegister(n.typ)
|
||||||
|
|
||||||
|
proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
|
||||||
|
dest, idx, value: TRegister) =
|
||||||
|
# opcLdObj et al really means "load address". We sometimes have to create a
|
||||||
|
# copy in order to not introduce false aliasing:
|
||||||
|
# mylocal = a.b # needs a copy of the data!
|
||||||
|
if needsAdditionalCopy(n):
|
||||||
|
var cc = c.getTemp(n.typ)
|
||||||
|
c.gABC(n, whichAsgnOpc(n), cc, value)
|
||||||
|
c.gABC(n, opc, dest, idx, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
|
else:
|
||||||
|
c.gABC(n, opc, dest, idx, value)
|
||||||
|
|
||||||
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
|
|
@ -1105,9 +1130,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
||||||
tyString, tyCString}:
|
tyString, tyCString}:
|
||||||
c.gABC(le, opcWrStrIdx, dest, idx, tmp)
|
c.preventFalseAlias(le, opcWrStrIdx, dest, idx, tmp)
|
||||||
else:
|
else:
|
||||||
c.gABC(le, opcWrArr, dest, idx, tmp)
|
c.preventFalseAlias(le, opcWrArr, dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkDotExpr, nkCheckedFieldExpr:
|
of nkDotExpr, nkCheckedFieldExpr:
|
||||||
# XXX field checks here
|
# XXX field checks here
|
||||||
|
|
@ -1115,12 +1140,12 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
let dest = c.genx(left.sons[0], {gfAddrOf})
|
let dest = c.genx(left.sons[0], {gfAddrOf})
|
||||||
let idx = genField(left.sons[1])
|
let idx = genField(left.sons[1])
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
c.gABC(left, opcWrObj, dest, idx, tmp)
|
c.preventFalseAlias(left, opcWrObj, dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkDerefExpr, nkHiddenDeref:
|
of nkDerefExpr, nkHiddenDeref:
|
||||||
let dest = c.genx(le.sons[0], {gfAddrOf})
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
c.gABC(le, opcWrDeref, dest, tmp)
|
c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let s = le.sym
|
let s = le.sym
|
||||||
|
|
@ -1129,24 +1154,32 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
withTemp(tmp, le.typ):
|
withTemp(tmp, le.typ):
|
||||||
c.gen(le, tmp, {gfAddrOf})
|
c.gen(le, tmp, {gfAddrOf})
|
||||||
let val = c.genx(ri)
|
let val = c.genx(ri)
|
||||||
c.gABC(le, opcWrDeref, tmp, val)
|
c.preventFalseAlias(le, opcWrDeref, tmp, 0, val)
|
||||||
c.freeTemp(val)
|
c.freeTemp(val)
|
||||||
else:
|
else:
|
||||||
if s.kind == skForVar: c.setSlot s
|
if s.kind == skForVar: c.setSlot s
|
||||||
internalAssert s.position > 0 or (s.position == 0 and
|
internalAssert s.position > 0 or (s.position == 0 and
|
||||||
s.kind in {skParam,skResult})
|
s.kind in {skParam,skResult})
|
||||||
var dest: TRegister = s.position + ord(s.kind == skParam)
|
var dest: TRegister = s.position + ord(s.kind == skParam)
|
||||||
|
if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}:
|
||||||
|
var cc = c.getTemp(le.typ)
|
||||||
|
gen(c, ri, cc)
|
||||||
|
c.gABC(le, whichAsgnOpc(le), dest, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
|
else:
|
||||||
gen(c, ri, dest)
|
gen(c, ri, dest)
|
||||||
else:
|
else:
|
||||||
let dest = c.genx(le, {gfAddrOf})
|
let dest = c.genx(le, {gfAddrOf})
|
||||||
genAsgn(c, dest, ri, requiresCopy)
|
genAsgn(c, dest, ri, requiresCopy)
|
||||||
|
|
||||||
proc genLit(c: PCtx; n: PNode; dest: var TDest) =
|
proc genLit(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
var opc = opcLdConst
|
# opcLdConst is now always valid. We produce the necessary copy in the
|
||||||
|
# assignments now:
|
||||||
|
#var opc = opcLdConst
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
elif c.prc.slots[dest].kind == slotFixedVar: opc = opcAsgnConst
|
#elif c.prc.slots[dest].kind == slotFixedVar: opc = opcAsgnConst
|
||||||
let lit = genLiteral(c, n)
|
let lit = genLiteral(c, n)
|
||||||
c.gABx(n, opc, dest, lit)
|
c.gABx(n, opcLdConst, dest, lit)
|
||||||
|
|
||||||
proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
|
proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
|
||||||
var n = newNode(nkType)
|
var n = newNode(nkType)
|
||||||
|
|
@ -1175,7 +1208,7 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
||||||
let dest = c.getTemp(s.typ)
|
let dest = c.getTemp(s.typ)
|
||||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||||
let tmp = c.genx(s.ast)
|
let tmp = c.genx(s.ast)
|
||||||
c.gABC(n, opcWrDeref, dest, tmp)
|
c.preventFalseAlias(n, opcWrDeref, dest, 0, tmp)
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
|
|
@ -1332,7 +1365,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
if a.sons[2].kind != nkEmpty:
|
if a.sons[2].kind != nkEmpty:
|
||||||
let tmp = c.genx(a.sons[0], {gfAddrOf})
|
let tmp = c.genx(a.sons[0], {gfAddrOf})
|
||||||
let val = c.genx(a.sons[2])
|
let val = c.genx(a.sons[2])
|
||||||
c.gABC(a, opcWrDeref, tmp, val)
|
c.preventFalseAlias(a, opcWrDeref, tmp, 0, val)
|
||||||
c.freeTemp(val)
|
c.freeTemp(val)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1342,6 +1375,13 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
else:
|
else:
|
||||||
if not fitsRegister(s.typ):
|
if not fitsRegister(s.typ):
|
||||||
c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
|
c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
|
||||||
|
let le = a.sons[0]
|
||||||
|
if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
|
||||||
|
var cc = c.getTemp(le.typ)
|
||||||
|
gen(c, a.sons[2], cc)
|
||||||
|
c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
|
else:
|
||||||
gen(c, a.sons[2], s.position.TRegister)
|
gen(c, a.sons[2], s.position.TRegister)
|
||||||
else:
|
else:
|
||||||
# assign to a.sons[0]; happens for closures
|
# assign to a.sons[0]; happens for closures
|
||||||
|
|
@ -1370,7 +1410,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
||||||
for x in n:
|
for x in n:
|
||||||
let a = c.genx(x)
|
let a = c.genx(x)
|
||||||
c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
|
c.preventFalseAlias(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
|
||||||
c.gABI(n, opcAddImmInt, tmp, tmp, 1)
|
c.gABI(n, opcAddImmInt, tmp, tmp, 1)
|
||||||
c.freeTemp(a)
|
c.freeTemp(a)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
@ -1402,7 +1442,8 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
|
if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
|
||||||
let idx = genField(it.sons[0])
|
let idx = genField(it.sons[0])
|
||||||
let tmp = c.genx(it.sons[1])
|
let tmp = c.genx(it.sons[1])
|
||||||
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
|
||||||
|
dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "invalid object constructor")
|
internalError(n.info, "invalid object constructor")
|
||||||
|
|
@ -1416,11 +1457,12 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
let idx = genField(it.sons[0])
|
let idx = genField(it.sons[0])
|
||||||
let tmp = c.genx(it.sons[1])
|
let tmp = c.genx(it.sons[1])
|
||||||
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
|
||||||
|
dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
else:
|
else:
|
||||||
let tmp = c.genx(it)
|
let tmp = c.genx(it)
|
||||||
c.gABC(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
|
c.preventFalseAlias(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
proc genProc*(c: PCtx; s: PSym): int
|
proc genProc*(c: PCtx; s: PSym): int
|
||||||
|
|
@ -1658,7 +1700,7 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||||
c.gABC(body, opcEof, eofInstr.regA)
|
c.gABC(body, opcEof, eofInstr.regA)
|
||||||
c.optimizeJumps(result)
|
c.optimizeJumps(result)
|
||||||
s.offset = c.prc.maxSlots
|
s.offset = c.prc.maxSlots
|
||||||
#if s.name.s == "find":
|
#if s.name.s == "get_data":
|
||||||
# echo renderTree(body)
|
# echo renderTree(body)
|
||||||
# c.echoCode(result)
|
# c.echoCode(result)
|
||||||
c.prc = oldPrc
|
c.prc = oldPrc
|
||||||
|
|
|
||||||
19
tests/casestmt/tcase_arrayconstr.nim
Normal file
19
tests/casestmt/tcase_arrayconstr.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
discard """
|
||||||
|
output: '''Not found!
|
||||||
|
Found!'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
const
|
||||||
|
md_extension = [".md", ".markdown"]
|
||||||
|
|
||||||
|
proc test(ext: string) =
|
||||||
|
case ext
|
||||||
|
of ".txt", md_extension:
|
||||||
|
echo "Found!"
|
||||||
|
else:
|
||||||
|
echo "Not found!"
|
||||||
|
|
||||||
|
test(".something")
|
||||||
|
# ensure it's not evaluated at compile-time:
|
||||||
|
var foo = ".markdown"
|
||||||
|
test(foo)
|
||||||
|
|
@ -2,7 +2,13 @@ discard """
|
||||||
msg: '''a
|
msg: '''a
|
||||||
s
|
s
|
||||||
d
|
d
|
||||||
f'''
|
f
|
||||||
|
TTaa
|
||||||
|
TTaa
|
||||||
|
TTaa
|
||||||
|
TTaa'''
|
||||||
|
|
||||||
|
output: '''test'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -18,3 +24,41 @@ macro test(): stmt =
|
||||||
echo i.s
|
echo i.s
|
||||||
|
|
||||||
test()
|
test()
|
||||||
|
|
||||||
|
|
||||||
|
# bug 1297
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
type TType = tuple[s: string]
|
||||||
|
|
||||||
|
macro echotest(): stmt =
|
||||||
|
var t: TType
|
||||||
|
t.s = ""
|
||||||
|
t.s.add("test")
|
||||||
|
result = newCall(newIdentNode("echo"), newStrLitNode(t.s))
|
||||||
|
|
||||||
|
echotest()
|
||||||
|
|
||||||
|
# bug #1103
|
||||||
|
|
||||||
|
type
|
||||||
|
Td = tuple
|
||||||
|
a:string
|
||||||
|
b:int
|
||||||
|
|
||||||
|
proc get_data(d: Td) : string {.compileTime.} =
|
||||||
|
result = d.a # Works if a literal string is used here.
|
||||||
|
# Bugs if line A or B is active. Works with C
|
||||||
|
result &= "aa" # A
|
||||||
|
#result.add("aa") # B
|
||||||
|
#result = result & "aa" # C
|
||||||
|
|
||||||
|
macro m(s:static[Td]) : stmt =
|
||||||
|
echo get_data(s)
|
||||||
|
echo get_data(s)
|
||||||
|
result = newEmptyNode()
|
||||||
|
|
||||||
|
const s=("TT", 3)
|
||||||
|
m(s)
|
||||||
|
m(s)
|
||||||
|
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -1,7 +1,8 @@
|
||||||
version 0.9.6
|
version 0.9.6
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- some table related tests are wrong (memory usage checks)
|
- integrate the new LL into the devel branch
|
||||||
|
- start experimental branch
|
||||||
|
|
||||||
Concurrency
|
Concurrency
|
||||||
-----------
|
-----------
|
||||||
|
|
@ -31,6 +32,7 @@ Misc
|
||||||
- type API for macros; make 'spawn' a macro
|
- type API for macros; make 'spawn' a macro
|
||||||
- markAndSweepGC should expose an API for fibers
|
- markAndSweepGC should expose an API for fibers
|
||||||
- prevent 'alloc(TypeWithGCedMemory)'
|
- prevent 'alloc(TypeWithGCedMemory)'
|
||||||
|
- some table related tests are wrong (memory usage checks)
|
||||||
|
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue