<br><br><div class="gmail_quote">On Tue, Jul 1, 2008 at 4:12 PM, Igor Stasenko &lt;<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>&gt; wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+1 to moving named primitive into image<br>
<br>
+1 to make use of primitive returning value (this would affect the<br>
code generator, but hell, its way better to have a notion why it<br>
failed than simply guessing in the dark room, &nbsp;like any currently<br>
primitive failure code does)<br>
<br>
+1 to eliminating pushRemappableOop:/popRemappableOop . (A question<br>
however, how you would handle heap overflows, when evil primitive<br>
generates massive object or lots of tiny objects?)</blockquote><div><br>It is much the same as it is now. &nbsp;A large allocation attempt (e.g. in primitiveNewWithArg) either succeed, possibly causing a garbage collection very soon after, or fails. &nbsp;The garbage collector is allowed to run in primitiveNewWithArg et al. &nbsp;But allocations at any other time cannot cause the garbage collector to run and are known to fit within the extra memory reserved for the interpreter. &nbsp;These allocations always succeed but may exceed some threshold which will cause a garbage collection very soon thereafter.<br>
<br>Memory will look something like this:<br>&nbsp;&nbsp; &nbsp;-&gt; &nbsp;start of heap<br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... lots of objects ...<br>&nbsp;&nbsp; &nbsp;-&gt; young start<br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... not so many objects ...<br>&nbsp;&nbsp; &nbsp;-&gt; free start/eden<br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... small amount of free space (a few hundred k) ...<br>
&nbsp;&nbsp; &nbsp;-&gt; scavenge threshold<br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... free memory (megabytes)...<br>&nbsp;&nbsp; &nbsp;-&gt; VM reserve start<br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .... very few k (e.g. 8k) ...<br>&nbsp;&nbsp; &nbsp;-&gt; fwd block reserve<br>&nbsp;&nbsp; &nbsp;-&gt; end<br><br>The allocation pointer is free start/eden. &nbsp;A new object is allocated here and advances free start/eden. &nbsp;We will dispense with freeBlock and its header for speed.<br>
<br>primitiveNewWithArg (et al) can allocate up to VM reserve start. &nbsp;An attempt beyond that can trigger a garbage collection but the retry cannot exceed VM reserve start.<br><br>Any other allocation can exceed VM reserve start but not fwd block reserve. &nbsp;Exceeding fwd block reserve is an internal fatal error that should not happen if VM reserve is large enough.<br>
<br>Any allocation that pushes free start/eden beyond scavenge threshold sets a flag that will cause the VM to perform an incrementalGC on the next send or backward branch.<br><br>The net result is that pointers only move during primitives that do substantial allocations (primitiveNewWithArg, anything that allocates lots of objects) and only these primitives need to use pushRemappableOop:/popRemappableOop.<br>
<br>The details can vary but the essentials are to arrange that for allocations in the course of execution (e.g. creating a block,creating the message argument of a doesNotUnderstand:, creating a primitive failure value, flushing a stack page to heap contexts, etc, etc) the garage collector will not run and so the VM does not need to manage pointers in local variables. &nbsp;It can assume these values will not change and remain valid until the next send or backward branch.<br>
<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">(a little OT .. )<br>
<br>
Another question, is how would you sync there changes with Hydra (if<br>
you having plans of course)?</blockquote><div><br>This *must* be done. &nbsp;I expect we&#39;ll spend quite a lot of time communicating to make this happen. &nbsp;I am about to extend the translator for the stack interpreter. &nbsp;But basically its my job to fit Cog into Hydra. <br>
<br>My own OT:<br><br> BTW, did you see my comment about renaming Hydra? &nbsp;I think &quot;String&quot; is a much better name. Strings are composed of threads. &nbsp;Smalltalk comes from Alan Kay&#39;s distaste for the kinds of names people were using for programming languages in the 60&#39;s &amp; 70&#39;s, names like Zeus and Thor. &nbsp;Hence Smalltalk. &nbsp;Hydra is another mythic name. &nbsp;Cog is a small element in a larger whole (and a cool advert by Honda). &nbsp;Anyway, think it over...<br>
<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">I have many changes in CodeGenerator and some in VMMaker , to simplify<br>
my day&#39;s job :)</blockquote><div><br>Could you email me your current VMMaker package, or a link to it? &nbsp;And could you summarise the changes you&#39;ve made and why? &nbsp;I&#39;ll do the same.<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
In fact, it would be good to make a clean refactoring of it:<br>
- make inst vars of Interpreter/ObjectMemory be the interpreter instance state<br>
- make class vars be the part of VM global state<br>
- make pool vars be the constants<br>
- same could be applied to methods (instance/class side)<br>
<br>
Currently things are little messy, since i made incremental changes to<br>
existing model.<br>
<br>
Another thing, which doesn&#39;t makes me sleep well, is that by using<br>
thread specific storage, it would be possible to avoid passing<br>
interpreter instance to each function/primitive. Too bad, GCC (on<br>
windows) support a __thread__ specifier only in latest release , which<br>
is &#39;technology preview&#39; how they calling it :)<br>
If we could use this, it would be possible to make Hydra nearly as<br>
fast as current Squeak VM.<br>
And there is no point to argue do we have right to use thread specific<br>
storage or not: consider that Hydra can run on platforms which can<br>
support threads. And since we already using threads, why we can&#39;t use<br>
thread-specific storage.</blockquote><div><br><br>You need is an abstraction layer, e.g. implemented with macros that insulates the Slang code form the platform thread system details. &nbsp;You then implement the abstraction layer as thinly as possible. &nbsp;I&#39;ve done this with the threaded API extension of the VW FFI. &nbsp;Its not hard. &nbsp;You may be able to find GPL versions out there.<br>
<br>best<br>Eliot<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">... (stopping OT)<br>
<br>
2008/7/1 Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;:<br>
<div><div></div><div class="Wj3C7c">&gt;<br>
&gt;<br>
&gt; On Tue, Jul 1, 2008 at 1:34 PM, tim Rowledge &lt;<a href="mailto:tim@rowledge.org">tim@rowledge.org</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On 1-Jul-08, at 1:20 PM, Eliot Miranda wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; One doesn&#39;t have to *use* the FFI. &nbsp; If the FFI isn&#39;t exposed via a<br>
&gt;&gt;&gt; primitive then no FFI. &nbsp;One can still have named primitives supported by the<br>
&gt;&gt;&gt; image and not by the VM and not use the FFI. &nbsp;To call a named primitive in a<br>
&gt;&gt;&gt; primitive plugin the following sequence occurs:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; the method containing a named primitive spec is activated and the<br>
&gt;&gt;&gt; primitive call fails because its function pointer is null.<br>
&gt;&gt;&gt; the failure code extracts the plugin name and invokes a primitive to load<br>
&gt;&gt;&gt; the plugin library<br>
&gt;&gt;&gt; the failure code extracts the primitive name and uses the lookup<br>
&gt;&gt;&gt; primitive to find the function in the loaded plugin library<br>
&gt;&gt;&gt; the failure code uses a primitive to slam the function pointer into the<br>
&gt;&gt;&gt; method<br>
&gt;&gt;&gt; the failure code uses the executeMethodWithArgs primitive to retry the<br>
&gt;&gt;&gt; bound named primitive method<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; So the FFI is an optional extra. &nbsp;One needs four primitives, load<br>
&gt;&gt;&gt; library, lookup name in library, insert primitive function pointer. and<br>
&gt;&gt;&gt; executemethodWithArgs (thanks Tim!). &nbsp;Slamming the function into the method<br>
&gt;&gt;&gt; could also be done using, say, objectAt:.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; So one can still have a nice small safe VM and have no direct support for<br>
&gt;&gt;&gt; named primitives in the VM.<br>
&gt;&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Leaving aside my like of all-named-prims, I *like* this enhancement to the<br>
&gt;&gt; support for named prims.<br>
&gt;&gt;<br>
&gt;&gt; It would slightly complicate the post-prim-call code in each method<br>
&gt;&gt; because you would need to handle the failed-to-find-prim case as well as all<br>
&gt;&gt; the prim-failed cases. It would be helped by an old idea that I&#39;m pretty<br>
&gt;&gt; sure eliot has plans for anyway (as indeed I have written about a few times)<br>
&gt;&gt; to add primitive error return values. For those that haven&#39;t heard of them,<br>
&gt;&gt; this is just a way of having the first temp in a context involved in a prim<br>
&gt;&gt; call be a slot for a return value from the prim if any error occurs. This<br>
&gt;&gt; means you can actually know wtf went wrong instead of guessing - &quot;ooh, was<br>
&gt;&gt; the first arg a SmallInteger? Um, if not, was it a Float that might round<br>
&gt;&gt; nicley? Err, was the second arg a ByteArray with the first byte = 255?&quot; etc.<br>
&gt;&gt; Instead you get &quot;ah, errorValue was 1, so we have to explode the reactor<br>
&gt;&gt; core in order to stop the Dreen from eating the children&quot;. Much nicer.<br>
&gt;<br>
&gt; I did primitive error codes at Cadence and they&#39;ll very probably b making it<br>
&gt; into Cog real soon now. &nbsp;They&#39;re simpler than VisualWorks&#39;, being only<br>
&gt; symbols. &nbsp;So extracting more information, such as a related error code<br>
&gt; requires a subsequent call. &nbsp;But I think the work I&#39;m doing right now on<br>
&gt; eliminating pushRemappableOop:/popRemappableOop will enable me to have a<br>
&gt; structured object with a name and parameters, which is more generally<br>
&gt; useful.<br>
&gt;<br>
&gt; A nice thing is that the code is forwards and backewards compatible. &nbsp;One<br>
&gt; can use the VM to run older images. &nbsp;One can run images that contain the<br>
&gt; primitive error code on older VMs, where one simply gets a nil error code on<br>
&gt; primitive failure.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
</div></div><font color="#888888">--<br>
Best regards,<br>
Igor Stasenko AKA sig.<br>
<br>
</font></blockquote></div><br>