<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hello Richard,<div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class=""> * The current APValue representation is extremely bloated. Each instance is 72 bytes, and every subobject of an object is stored as a distinct APValue, so for instance a single char[128] variable will often occupy 9288 bytes of storage and incurs 128 distinct memory allocations.</div></div></div></blockquote><div><br class=""></div><div>Arrays and structures will be stored in a compact, contiguous form in memory, so we can save a lot of space here.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class=""> * The current representation of an lvalue as an explicit subobject path is likewise very expensive in terms of memory and distinct allocations.</div></div></div></blockquote><div><br class=""></div><div>LValues are simply pointers in the VM. Pointers into structures will be a combination of a block and a descriptor: the</div><div>block represents the allocated memory, while the descriptor characterises the current field and limits what is accessible</div><div>through the pointer. There should be a unique descriptor for each field, so this option is more compact.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="">I have some pretty concrete ideas for how to solve these problems that I could write up if you're interested in tackling them.</div></div></div></blockquote><div><br class=""></div><div>Would be great - we do have some ideas on how to proceed, but we'd appreciate any other input. One thing to mention is that</div><div>we first want a working and simple implementation which leaves the door open for further optimisations. We would like to avoid</div><div>optimisations now if they come with significant complexity.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="">(Your project name makes me cringe a little; maybe referring to it as ExprVM to match the subdirectory name would be better?)</div></div></div></blockquote><div><br class=""></div><div>I'll let JF Bastien argue this point.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote"><div class="">Minor point: while the depth limit does exist primarily to work around problems caused by the recursive implementation, the steps limit is provided to catch infinite loops. (I assume your point is that we could raise this limit commensurately with any performance improvements in the evaluator; that seems reasonable.)</div></div></div></div></blockquote><div><br class=""></div><div>The numbers are a ballpark measure either way - we could allow the VM to run 10x the number of steps if we expect it to be faster.</div><div>But this is something to be implemented in the future. Same goes for recursion depth, although we could experiment with tail call</div><div>elimination as well.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote"><div class="">I notice that this is effectively building another system to convert the AST into a control flow graph. Have you considered using the existing CFG layer for (the majority of) this?</div></div></div></div></blockquote><div><br class=""></div><div>The bytecode is just a linear sequence of instructions - we do not build a CFG or explicit basic blocks at any point.</div><div>I guess that would be required if we were to apply non-trivial optimisations, but that is not planned. We perform</div><div>some peephole optimisations and emit specialised opcodes, but we do not plan to go beyond that as we are not sure</div><div>the optimisations would pay for themselves. Given that diagnostics are required whenever UB is encountered,</div><div>the opportunities are severely limited.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote"><div class="">There are a bunch of other ways that pointers might be invalidated, due to lifetime events rather than storage events. For example, changing the active member of a union would prevent access through old pointers to the old active member, and changing the active union member /back/ would make such accesses valid again. Similarly, an explicit destructor call on an object prevents that object from being used, but certain other operations can bring it back to life and make the old pointers / references usable again. How do you intend to handle such cases?</div></div></div></div></blockquote><div><br class=""></div><div>The present implementation requires all allocated blocks to track all pointers which point to them. This</div><div>mechanism should allow unions and invalidation to be implemented. This is obviously not the fastest</div><div>option and we definitely need to think more about the invalidation aspect. Up until now, we mostly </div><div>considered the lifetime problem and a GC-like solution to it, but invalidation further complicates that.</div></div></div><div class=""><br class=""></div><div class="">Thank you,</div><div class="">Nandor Licker</div></body></html>