Fwd: Mirror primitives [Was The better debugger support by extending an Object protocol]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Fwd: Mirror primitives [Was The better debugger support by extending an Object protocol]

Eliot Miranda-2
 
---------- Forwarded message ----------
From: Eliot Miranda <[hidden email]>
Date: Mon, Sep 7, 2009 at 11:56 AM
Subject: Mirror primitives [Was The better debugger support by
extending an Object protocol]
To: The general-purpose Squeak developers list
<[hidden email]>


Hi Igor,

On Mon, Sep 7, 2009 at 10:29 AM, Igor Stasenko <[hidden email]> wrote:

>
> 2009/9/7 Bert Freudenberg <[hidden email]>:
> >
> > On 07.09.2009, at 18:40, Randal L. Schwartz wrote:
> >
> >>>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
> >>
> >> Igor> Here is the default implementation of
> >>
> >> Object> debugPrintOn: aStream
> >> Igor>   ^ self printOn: aStream
> >>
> >> I like it, but I don't like the name.  It conjurs up the idea of debugging
> >> the #printOn: method itself.
> >>
> >> maybe #printForDebuggerOn: ?
> >
> >
> > It matches the other methods like #longPrintOn: though.
> >
> > Also that would imply only the debugger invokes it, when it's clearly
> > appropriate for any purpose.
> >
> > However, apart from this bike shedding ;) do others think it's a good idea
> > in general? IMHO #printOn: is primarily used for debugging anyway so I
> > wouldn't really expect a separate debug print method to be needed. Debugging
> > transparent proxies isn't for the faint-of-heart anyway, so these developers
> > can adapt their tools and proxies I would guess. OTOH there is precedence in
> > e.g. #asExplorerString, which exists solely to get rid of the quotes
> > enclosing strings for aesthetic reasons ...
> >
>
> I agree with you Bert, that we should consider if its really necessary.
> While #printOn: is used by most code for debugging, some of the code
> using it to serialize object to textual stream, so the #printOn: usage
> is much more generic than just debugging.
>
> As for debugging the transparent proxies - yes you can make own
> tools.. but this means reimplementing/hacking
> other tools , like debugger, inspector and so on, which will probably
> end up with similar solution to what i proposing.
>
> For example, there was a point of discrepancy with debugging the code
> which uses Magma.
> The magma forwarding proxy reifying the object once the first real
> message is sent to it.
> And the problem with such a proxy, that you can't use them in certain
> situations, like:
>
> self perform: aSelectorProxied with: #foo
>
> because #perform doesn't sends the messages to aSelectorProxied and
> primitive fails. But then, when you entering the debugger and trying
> to figure out why its not working - a proxy becomes a real object when
> it printed out.. and so you can't debug the error using debugger.
> Which leaves you to wonder, why code works in debugger, but not
> working at run time :)
I have fixes for this integrated in Qwaq.  This is work I did for
VisualWorks a while back.  The idea is to add a set of mirror
primitives, so called because they do reflection, to ContextPart.
These primitives implement the basic operations of the object model
needed for execution simulation, fetching an object's class, accessing
its named and indexed instance variables, and the number of indexed
instance variables, sending a message, but they take the object
operated on as a parameter and so do function without sending messages
to that object.  These primitives are then used by the execution
simulation machinery to correctly simulate the execution of the
virtual machine irrespective of the class and/or messages implemented
by the receiver.

For example, (eschewing HTML for Bert's contentment)

ContextPart methods for mirror primitives
object: anObject instVarAt: anIndex
       "Primitive. Answer a fixed variable in an object. The numbering of the
        variables corresponds to the named instance variables. Fail if the index
        is not an Integer or is not the index of a fixed variable.
Essential for the
        debugger. See  Object documentation whatIsAPrimitive."

       <primitive: 73>
       "Access beyond fixed variables."
       ^self object: anObject basicAt: anIndex - (self objectClass:
anObject) instSize

object: anObject instVarAt: anIndex put: aValue
       "Primitive. Store a value into a fixed variable in the argument anObject.
        The numbering of the variables corresponds to the named instance
        variables.  Fail if the index is not an Integer or is not the index of a
        fixed variable.  Answer the value stored as the result. Using this
        message violates the  principle that each object has sovereign control
        over the storing of values into its instance variables.
Essential for the
        debugger. See Object documentation whatIsAPrimitive."

       <primitive: 74>
       "Access beyond fixed fields"
       ^self object: anObject basicAt: anIndex - (self objectClass:
anObject) instSize put: aValue

ContextPart methods for instruction decoding
pushReceiverVariable: offset
       "Simulate the action of bytecode that pushes the contents of
the receiver's
       instance variable whose index is the argument, index, on the
top of the stack."

       self push: (self object: self receiver instVarAt: offset + 1)

popIntoReceiverVariable: offset
       "Simulate the action of bytecode that removes the top of the stack and
       stores it into an instance variable of my receiver."

       self object: self receiver instVarAt: offset + 1 put: self pop

storeIntoReceiverVariable: offset
       "Simulate the action of bytecode that stores the top of the stack into an
       instance variable of my receiver."

       self object: self receiver instVarAt: offset + 1 put: self top

The attached change set for the image level code is also conflated
with changes that allow the debugger to set the primitive error code
correctly.


The VM also needs to implement the primitives.  If the order of the
arguments are the same as those of the corresponding non-reflective
primitive (e.g. aContext object: theReceiver instVarAt: index put:
value has the same order as theReceiver instVarAt: index put: value)
and the primitive pops back the stack using self pop: argumentCount +
1, one can use the same VM primitive implementations as the
non-reflective ones and so avoid needing extra primitives.

However, not all primitives are correctly implemented; e.g. at: and
at:put: are, but size is not.  So before we can use this there is some
work to do in the standard VMs.  I'm attaching here the implementation
in the Stack VM which will require some back porting to the standard
VM.  None of these changes has performance implications because the
special selector impelmentations of at: at:put: size and #== are not
affected.

With the above changes one can safely step through code that uses
proxies that do not inherit from Object, or even ProtoObject.  I still
need to implement a PrimitiveObjectInspector, or use the mirror
primitives in implementing the Inspector.  However, there is one more
important thing needed in the debugger which these changes do not
address and that is the value of Processor activeProcess within  the
debugger.  e.g. "print it" the following:

| thisProcessOutsideTheDebugger thisProcessInsideTheDebugger |
thisProcessOutsideTheDebugger := Processor activeProcess.
self halt.
thisProcessInsideTheDebugger := Processor activeProcess.
'Send to here (Into) then proceed'.
thisProcessOutsideTheDebugger == thisProcessInsideTheDebugger

This will potentially break debugging of servers that maintain process
pools.  Andreas has proposed a very simple fix for this.  Add an
instance variable to Process called, e.g. effectiveProcess, which is
nil in normal processes.  When the debugger runs it sets
effectiveProcess to that of the process which it is debugging and
Processor activeProcess is implemented as something like

ProcessorScheduler methods for accessing
activeProcess
   ^activeProcess effectiveProcess ifNil: [activeProcess]

I'll try and get round to this soon.


I'm posting this rather than integrating because a) the VMs need to
get updated before we can use the image level code and, b) the VM
folks need code to test their VMs with.  I'm happy to integrate the
image-level changes once the VMs have been upgraded.

best
Eliot

>
> >
> > - Bert -
> >
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>

MirrorPrimitives.st (32K) Download Attachment
MirrorPrimitivesVM.st (14K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Fwd: Mirror primitives [Was The better debugger support by extending an Object protocol]

David T. Lewis
 
On Mon, Sep 07, 2009 at 12:13:07PM -0700, Eliot Miranda wrote:

>
> The attached change set for the image level code is also conflated
> with changes that allow the debugger to set the primitive error code
> correctly.
>
>
> The VM also needs to implement the primitives. ?If the order of the
> arguments are the same as those of the corresponding non-reflective
> primitive (e.g. aContext object: theReceiver instVarAt: index put:
> value has the same order as theReceiver instVarAt: index put: value)
> and the primitive pops back the stack using self pop: argumentCount +
> 1, one can use the same VM primitive implementations as the
> non-reflective ones and so avoid needing extra primitives.
>
> However, not all primitives are correctly implemented; e.g. at: and
> at:put: are, but size is not. ?So before we can use this there is some
> work to do in the standard VMs. ?I'm attaching here the implementation
> in the Stack VM which will require some back porting to the standard
> VM. ?None of these changes has performance implications because the
> special selector impelmentations of at: at:put: size and #== are not
> affected.

<snip>

> I'm posting this rather than integrating because a) the VMs need to
> get updated before we can use the image level code and, b) the VM
> folks need code to test their VMs with. ?I'm happy to integrate the
> image-level changes once the VMs have been upgraded.
>
> best
> Eliot

I opened a Mantis issue to track this, and uploaded Eliot's fileouts:
  Mantis 7429: Add Mirror Primitives to the VM
  http://bugs.squeak.org/view.php?id=7429

A bit of work will be required to integrate the mirror primitives in
MirrorPrimitivesVM.st into the base Squeak VM (this has not yet been
done). Note that unit tests for the mirror primitives are present in
the Squeak trunk image, which of course fail without VM support,
so there is some interest in getting this integrated into the VM to
support the tests in the image.

Dave