[squeak-dev] re: MicroSqueak

Igor Stasenko siguctua at gmail.com
Tue Mar 3 01:18:31 UTC 2009


2009/3/3 Eliot Miranda <eliot.miranda at gmail.com>:
>
>
> On Mon, Mar 2, 2009 at 3:51 PM, Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
>>
>>
>> On Mon, Mar 2, 2009 at 3:25 PM, Igor Stasenko <siguctua at gmail.com> wrote:
>>>
>>> 2009/3/3 Eliot Miranda <eliot.miranda at gmail.com>:
>>> - Show quoted text -
>>> - Show quoted text -
>>> >
>>> >
>>> > On Mon, Mar 2, 2009 at 1:48 PM, Stephen Pair <stephen at pairhome.net>
>>> > wrote:
>>> >>
>>> >> On Mon, Mar 2, 2009 at 12:38 AM, Eliot Miranda
>>> >> <eliot.miranda at gmail.com>
>>> >> wrote:
>>> >>>
>>> >>>
>>> >>> On Sun, Mar 1, 2009 at 9:20 PM, Craig Latta <craig at netjam.org> wrote:
>>> >>>>
>>> >>>> [snip]
>>> >>>>     As for whether to produce an object memory statically and then
>>> >>>> set
>>> >>>> it running, or transform an object memory which is always running...
>>> >>>> I think
>>> >>>> the resulting memory will need to load modules live anyway, so one
>>> >>>> might as
>>> >>>> well do all the transformations that way. Perhaps this is simply an
>>> >>>> aesthetic choice.
>>> >>>
>>> >>> Surely repeatability mandates that one roduce an object memory
>>> >>> statically
>>> >>> and then set it running?  Because of things like delays the always
>>> >>> running
>>> >>> memory is almost never in a predictable state, so one always ends up
>>> >>> with
>>> >>> different bits even if they represent the same functionality.
>>> >>> E.
>>> >>
>>> >> Maybe you could get the repeatability with a process that is roughly:
>>> >> a) write the spec for the capability of the image (a method that
>>> >> exercises
>>> >> everything you want to be able to do)
>>> >> b) use the class/method copying & DNU trickery and do the runtime
>>> >> analysis
>>> >> to figure out the classes and methods needed to support that
>>> >> capability
>>> >> c) do something a little more surgical to build a new image by copying
>>> >> over the behaviors and methods, but construct the processes and stacks
>>> >> more
>>> >> deliberately (so you aren't so tied to the running image's state)
>>> >> I'd think in this way you could do something that was reproducible to
>>> >> the
>>> >> extent that resulting image was only dependent on the running image
>>> >> for its
>>> >> behaviors and other necessary objects (various singletons and
>>> >> whatnot), but
>>> >> otherwise not affected by various processes and random other things
>>> >> that
>>> >> might be in that image.  Once you had (b) and (c) mostly ironed out,
>>> >> it
>>> >> would be a process of refining the specification in (a) to get to a
>>> >> suitable
>>> >> minimal image.
>>> >
>>> > Agreed.  The nice thing is being able to run a) in the IDE so that when
>>> > something is missing it manifests as an Undeclared or an MNU.
>>> > One thing is ensuring that when simulating objects like nil, true and
>>> > false
>>> > behave as they will in the result, not as defined in the host image.
>>> >  One
>>> > thing one could do is arrange that the compiler for MObject uses
>>> > instances
>>> > of MSymbol for all code under MObject.  Then e.g. a doesNotUnderstand:
>>> > handler on SmallInteger, UndefinedObject, Boolean et al might be able
>>> > to
>>> > forward things correctly and arrange that the simulation was more
>>> > accurate.
>>> >
>>>
>>> - Show quoted text -
>>> Thats why i wrote own parser/compiler in Moebius.
>>> It is designed in a way, that a parser & compiler output is under full
>>> control of an object which plays role as environment.
>>> So, you can produce an instance of CompiledMethod as output, or encode
>>> result in machine code, or represent methods as a raw bytes which then
>>> could be put in the image you constructing.
>>> Even nil,true,false singleton values are under control of environment.
>>>
>>> Read more about it here.
>>> http://code.google.com/p/moebius-st/wiki/Parser
>>>
>>> Simulation of SmallInts could be made easy - we could simply make a
>>> class, named BoxedSmallInteger
>>> and use it for representing all literal values in methods. At final
>>> stage of image creating we can unbox them and replace by smallints.
>>
>> Cool.  So the compiler can avoid using the pushNil, pushFalse and pushTrue
>> bytecodes.  It must send some message to coerce every MBoolean result into a
>> host Boolean before doing a conditional jump.  It must wrap all
>> MSmallInteger relational primitive invocations with code to coerce the
>> Booleran to the matching MBoolean.

right , something like:

MSmallInteger >> #<
< object
   ^ MBoolean from: boxed < object boxedValue

>> A doesNotUnderstand: will produce an instance of Message and send
>> doesNotUnderstand:, do MObject needs a doesNtUnderstand: handler that sends
>> MSymbol #doesNotUnderstand: with a coercion of the Message to an MMessage.

why care converting it, when you can simply replace a Message class
with MMessage in special objects array, while running a 'sandboxed'
code :)

Second thing about #doesNotUnderstand:
Often people forgetting that some classes could have own custom
#doesNotUnderstand: method.
I'd rather do not put any expectations on DNU while designing
micro-image bootstrapper.

And i seem missing the direction where this discussion turned out.
Where/when we would want to run a code in host environment?

In Moebius, since it is hosted in Squeak, and since we having better
parser ;) i could simulate the method behavior at multiple stages
including just after parsing a method.
I created a simple MockContext class, which can evaluate things
strictly in a manner how it is parsed from method source.
This, for instance, allows us to test parser output in a complete
black-box fashion:

testEvaluateParserOutput
	| method |
	
	method := self parse: ' = x  ^ x == self ' class: Object.
	self assert: [
		(CVMockContext evaluate: method arguments: #(1 1)) == true.].
	self assert: [
		(CVMockContext evaluate: method arguments: #(true false)) == false.]

testEvaluateParserOutput2
	| method |
	method := self parse: ' foo ^ #(nil true false) ' class: Object.
	self assert: [
		(CVMockContext evaluate: method arguments: #(nil)) = #(nil true false)].
	method := self parse: ' foo ^ #(#a #b #c) ' class: Object.
	self assert: [
		(CVMockContext evaluate: method arguments: #(nil)) = #(#a #b #c)].
	method := self parse: ' foo ^ #() ' class: Object.
	self assert: [
		(CVMockContext evaluate: method arguments: #(nil)) = #()].
	
note, that 'method' above is not a CompiledMethod, it is an AST form
of parsed source, encoded as lambda message sends.


>>  Any other holes that need to be plugged?
>> Alternatively just create a subclass of InstructionStream and/or
>> ContextPart and interpret all code and have the interpretation manage
>> MObject.  That might be slow but easier to get going.

>
> But perhaps a better alternative is just to use Hydra and provide a remote
> debugging interface to another Hydra space.  So there's a version of the
> Hydra spawn operation that constructs the heap from MObject.  That machinery
> would be easy to extend, right Igor?

Right, this is what i'm writing between the lines :)
I willing to have a generic toolset which could easily produce a
micro-images for any purposes, including a kernel-image, of course.
Lately , we discussed a one more little primitive for Hydra with Klaus
, and one more kind of channel - an object channel. It will allow you
to transfer objects (even cloning a subgraphs) between images , not
just dumb raw number of bytes :) This could ease developing tools
which require interaction between images, because you don't have to
care about serializing/deserializing stuff - you literally just send
what you want to other side.

> How about the remote debugging?  How minimal is the debugging stub that must
> exist in the spawned MImage? Would one need VM changes (e.g. a callback
> handler for a recursive doesNotUnderstand: error)?
>

I think that putting debugger support into VM will be a big mistake.
Debugging is a fairly complex domain, and i don't think that we need
to deal with this at VM level, where is no objects but oops, headers &
bits.. This is right way to get a hellishly complex & unmanageable
artifact.

Debugger, as anything else is invoked using regular message send -
(during Error>>signal). So, it is easy to hook into it and turn into
right direction.
I made a simple class HydraDebugToolSet, which replaces an image
default toolset for images which running in background.
In result, when error happens, it sends an error message to a
#transcript channel of main interpreter.
Nothing stops us from getting a bit further and request main
interpreter to establish a remote debugging session (except that we
don't have Debuggers with remote debugging capabilities ;) ).
But i know there is already at least one remote debugger
implementation in Squeak - GemStone tools. It is using OB tools to
generate UI & other stuff.
I'm not sure, what license it having, and could it be took as base for
remote debugging tool for Squeak.
(it would be nice to have a basic remote debugging framework in
squeak, which could allow different backends - either G/S , remote
socket connection, or via Hydra channels).

>>> We're in smalltalk, after all, where such things is possible to do,
>>> unlike many other languages :)
>>
>> Right on!
>>
>>>
>>> >>
>>> >> - Stephen
>>> - Show quoted text -
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>


-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list