Re: Debugger: PLEASE READ [was Re: [squeak-dev] Request for feedback: mirrors]

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

Re: Debugger: PLEASE READ [was Re: [squeak-dev] Request for feedback: mirrors]

Eliot Miranda-2
So given that the Interpreter VM now supports the mirror primitives, does anyone object if I add the debugger changes to trunk that use the mirror primitives and hence make accurate debugging of proxies possible?  The downside of doing this is that the debugger will be broken on older VMs.

As an example of the changes here are the old and new methods form pushing an inst var in the debugger/execution simulator.  The first one sends a message to the receiver, and hence if it is a proxy will invoke the proxy's doesNotUnderstand: handling rather than answering the relevant inst var.  The second one directly accesses the relevant inst var, accurately simulating what the VM does for the bytecode.  The changes replace direct sends with use of mirror primitives throughout execution simulation in all the places where the VM would do a direct access rather than send a message.

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 receiver instVarAt: offset + 1)

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)

and here's the mirror method.  c.f. Object>instVarAt:.  They share the same primitive number because internally the VM implements varargs primitives.
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

On Tue, May 22, 2012 at 8:17 PM, David T. Lewis <[hidden email]> wrote:
On Tue, May 22, 2012 at 03:24:34PM -0700, Eliot Miranda wrote:
> On Tue, May 22, 2012 at 12:07 AM, Colin Putney <[hidden email]> wrote:
>
> > Hi all,
> >
> > I've just uploaded a package to the Inbox for review by the community:
> >
> > http://source.squeak.org/inbox/Mirrors-cwp.2.mcz
> >
> > It's a simple first step at creating a mirror API for Squeak. I've only
> > implemented ObjectMirror and ObjectVmMirror, which provide high- and
> > low-level reflection on an object. This implementation has a twist,
> > however: it sends no messages to the object it's reflecting. That allows us
> > to reflect on network proxies, ORM stubs, mock objects and the like without
> > triggering any state changes.
> >
> > As a proof of the concept, I've implemented a rudimentary non-invasive
> > MirrorInspector. The main thing that's missing is non-invasive printing,
> > which would take a bit of work to implement, but isn't necessary for a
> > demo. To see it in action do try the following in a workspace.
> >
> > WARNING: Read the comments carefully, and don't do this in an image you
> > care about!
> >
> > "This creates a very dangerous object"
> > Object subclass: #Nuke
> > instanceVariableNames: 'one two three'
> > classVariableNames: ''
> > poolDictionaries: ''
> > category: 'Test'.
> > class := Smalltalk at: #Nuke.
> > class superclass: nil.
> > inst := class basicNew.
> >
> > "This is harmless"
> > MirrorInspector inspect: inst.
> >
> > "This will crash your image"
> > inst yourself.
> >
> > The implementation uses primitive 188 to directly execute CompiledMethods
> > with the reflected object as the receiver, thus giving us access to the
> > object's state without sending it a message.
> >
>
> In part you can use the light-weigth mirror methods in ContextPart, these
> take the object operated on as an argument.  Non-invasive printing could be
> done via execution simulation.  I've already modified the Squeak debugger
> in Qwaq/Teleplace images to use these light-weight mirror primitives so
> that messages are not sent to receivers when simulating execution in the
> debugger (i.e. when doing send instead of step).  If the mirror primitives
> now work on the interpreter I can fold this into trunk.  David, do the
> mirror primitive tests pass on the interpreter?

All mirror primitive tests pass on the interpreter VM if built with the
latest VMMaker and SVN sources. However, the mirror primitive support is
not yet present in any officially released standard VM.

The updates for mirror primitive support were added in VMMaker-dtl.262 and
VMMaker-dtl.261. Note the update comment in VMMaker-dtl.262, as the
implementation differs from Cog and a code review would be welcome:

   Name: VMMaker-dtl.262
   Author: dtl
   Time: 5 January 2012, 12:41:29.745 am

   VMMaker 4.7.19

   Reference Mantis 7429: Add Mirror Primitives to the VM

   Update primitivePerformInSuperclass to support ContextPart>>object:perform:withArguments:inClass:

   Implementation differs from that of oscog in that the original primitivePerformAt:
   is retained unmodified, and the necessary stack adjustments are done in
   primitivePerformInSuperclass for the special case of argumentCount 4
   (mirror primitive call) rather than 3. The oscog approach may be prefered
   (not least for its clearer method naming), but making the change in
   primitivePerformInSuperclass is low risk and more easily implemented by
   a Sunday Squeaker.

   All MirrorPrimitiveTests pass.

Dave





--
best,
Eliot



Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

Andreas.Raab
On 5/23/2012 20:51, Eliot Miranda wrote:
> So given that the Interpreter VM now supports the mirror primitives,
> does anyone object if I add the debugger changes to trunk that use the
> mirror primitives and hence make accurate debugging of proxies possible?
> The downside of doing this is that the debugger will be broken on
> older VMs.

It should be possible to write the mirror prims relatively safely, e.g.:

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>
        anIndex <= (self objectClass: anObject) instSize
                ifTrue:["Assume mirror primitives are missing"
                        ^anObject instVarAt: index]
                ifFalse:["Access beyond fixed variables."
                        ^self object: anObject basicAt: anIndex - (self objectClass:
anObject) instSize].



Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

Eliot Miranda-2


On Wed, May 23, 2012 at 12:04 PM, Andreas Raab <[hidden email]> wrote:
On 5/23/2012 20:51, Eliot Miranda wrote:
So given that the Interpreter VM now supports the mirror primitives,
does anyone object if I add the debugger changes to trunk that use the
mirror primitives and hence make accurate debugging of proxies possible?
The downside of doing this is that the debugger will be broken on
older VMs.

It should be possible to write the mirror prims relatively safely, e.g.:

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>
       anIndex <= (self objectClass: anObject) instSize
               ifTrue:["Assume mirror primitives are missing"
                       ^anObject instVarAt: index]
               ifFalse:["Access beyond fixed variables."
                       ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize].

That's a good idea.  Alas it doesn't work because the primitives won't fail on the older VMs.  Note that the same primitive is used for instVarAt: and object:instVarAt: (and likewise for object:instVarAt:put: & objectClass: etc).  The difference is that in the older VM the prims assume a fixed argument count and only pop that many objects from the stack.  Hence there is the potential of stack overflow in the older VMs.  In any case things are likely to limp along rather than fail catastrophically.  I'm not sure that that's a good thing or not ;)
 



Cheers,
 - Andreas




--
best,
Eliot



Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: [squeak-dev] Request for feedback: mirrors]

Stéphane Rollandin
In reply to this post by Eliot Miranda-2
>   The downside of doing this is that the debugger will be broken on
> older VMs.

Which ones ?

Stef

Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: [squeak-dev] Request for feedback: mirrors]

David T. Lewis
On Wed, May 23, 2012 at 09:46:51PM +0200, St?phane Rollandin wrote:
> >  The downside of doing this is that the debugger will be broken on
> >older VMs.
>
> Which ones ?
>

None of the officially released interpreter VMs contain mirror
primitive support.

Mirror primitive support is present in the source code (VMMaker) for
the interpreter VM and has been tested to the extent that it passes
the unit tests. Presumably this means that the debugger changes will
work with a newly build interpreter VM, although I cannot confirm this.

If the image support can be added in the manner suggested by Andreas,
that would be great. Otherwise, maybe not so good.

Dave


Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

David T. Lewis
In reply to this post by Eliot Miranda-2
On Wed, May 23, 2012 at 12:30:48PM -0700, Eliot Miranda wrote:

> On Wed, May 23, 2012 at 12:04 PM, Andreas Raab <[hidden email]> wrote:
>
> > On 5/23/2012 20:51, Eliot Miranda wrote:
> >
> >> So given that the Interpreter VM now supports the mirror primitives,
> >> does anyone object if I add the debugger changes to trunk that use the
> >> mirror primitives and hence make accurate debugging of proxies possible?
> >> The downside of doing this is that the debugger will be broken on
> >> older VMs.
> >>
> >
> > It should be possible to write the mirror prims relatively safely, e.g.:
> >
> > 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>
> >        anIndex <= (self objectClass: anObject) instSize
> >                ifTrue:["Assume mirror primitives are missing"
> >                        ^anObject instVarAt: index]
> >                ifFalse:["Access beyond fixed variables."
> >                        ^self object: anObject basicAt: anIndex - (self
> > objectClass: anObject) instSize].
> >
>
> That's a good idea.  Alas it doesn't work because the primitives won't fail
> on the older VMs.  Note that the same primitive is used for instVarAt: and
> object:instVarAt: (and likewise for object:instVarAt:put: & objectClass:
> etc).  The difference is that in the older VM the prims assume a fixed
> argument count and only pop that many objects from the stack.  Hence there
> is the potential of stack overflow in the older VMs.  In any case things
> are likely to limp along rather than fail catastrophically.  I'm not sure
> that that's a good thing or not ;)

What's the actual failure mode? If you run an image with the updated
mirroring debugger on a Squeak-4.4.7.2357 VM from http://squeakvm.org/unix/
what actually happens? Does the debugger work at all? Does the image get
messed up from calling primitives with the wrong number of arguments? Does
the VM crash after a while?

Dave


Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

David T. Lewis
In reply to this post by Eliot Miranda-2
On Wed, May 23, 2012 at 12:30:48PM -0700, Eliot Miranda wrote:

> On Wed, May 23, 2012 at 12:04 PM, Andreas Raab <[hidden email]> wrote:
>
> > On 5/23/2012 20:51, Eliot Miranda wrote:
> >
> >> So given that the Interpreter VM now supports the mirror primitives,
> >> does anyone object if I add the debugger changes to trunk that use the
> >> mirror primitives and hence make accurate debugging of proxies possible?
> >> The downside of doing this is that the debugger will be broken on
> >> older VMs.
> >>
> >
> > It should be possible to write the mirror prims relatively safely, e.g.:
> >
> > 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>
> >        anIndex <= (self objectClass: anObject) instSize
> >                ifTrue:["Assume mirror primitives are missing"
> >                        ^anObject instVarAt: index]
> >                ifFalse:["Access beyond fixed variables."
> >                        ^self object: anObject basicAt: anIndex - (self
> > objectClass: anObject) instSize].
> >
>
> That's a good idea.  Alas it doesn't work because the primitives won't fail
> on the older VMs.  Note that the same primitive is used for instVarAt: and
> object:instVarAt: (and likewise for object:instVarAt:put: & objectClass:
> etc).  The difference is that in the older VM the prims assume a fixed
> argument count and only pop that many objects from the stack.  Hence there
> is the potential of stack overflow in the older VMs.  In any case things
> are likely to limp along rather than fail catastrophically.  I'm not sure
> that that's a good thing or not ;)

Would it be possible to perform one test at image startup time to determine
if mirror primitive support is present, and handle things accordingly from
then on?

Dave


Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

Eliot Miranda-2


On Wed, May 23, 2012 at 2:13 PM, David T. Lewis <[hidden email]> wrote:
On Wed, May 23, 2012 at 12:30:48PM -0700, Eliot Miranda wrote:
> On Wed, May 23, 2012 at 12:04 PM, Andreas Raab <[hidden email]> wrote:
>
> > On 5/23/2012 20:51, Eliot Miranda wrote:
> >
> >> So given that the Interpreter VM now supports the mirror primitives,
> >> does anyone object if I add the debugger changes to trunk that use the
> >> mirror primitives and hence make accurate debugging of proxies possible?
> >> The downside of doing this is that the debugger will be broken on
> >> older VMs.
> >>
> >
> > It should be possible to write the mirror prims relatively safely, e.g.:
> >
> > 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>
> >        anIndex <= (self objectClass: anObject) instSize
> >                ifTrue:["Assume mirror primitives are missing"
> >                        ^anObject instVarAt: index]
> >                ifFalse:["Access beyond fixed variables."
> >                        ^self object: anObject basicAt: anIndex - (self
> > objectClass: anObject) instSize].
> >
>
> That's a good idea.  Alas it doesn't work because the primitives won't fail
> on the older VMs.  Note that the same primitive is used for instVarAt: and
> object:instVarAt: (and likewise for object:instVarAt:put: & objectClass:
> etc).  The difference is that in the older VM the prims assume a fixed
> argument count and only pop that many objects from the stack.  Hence there
> is the potential of stack overflow in the older VMs.  In any case things
> are likely to limp along rather than fail catastrophically.  I'm not sure
> that that's a good thing or not ;)

Would it be possible to perform one test at image startup time to determine
if mirror primitive support is present, and handle things accordingly from
then on?

Of course but it'll be clumsy.  It'll necessitate a layer of wrapper methods, and for what purpose?  Better IMO to upgrade the VMs asap.

 

Dave





--
best,
Eliot



Reply | Threaded
Open this post in threaded view
|

Re: Debugger: PLEASE READ [was Re: Request for feedback: mirrors]

Andreas.Raab
In reply to this post by Eliot Miranda-2
On 5/23/2012 21:30, Eliot Miranda wrote:

>
>
> On Wed, May 23, 2012 at 12:04 PM, Andreas Raab <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     On 5/23/2012 20:51, Eliot Miranda wrote:
>
>         So given that the Interpreter VM now supports the mirror primitives,
>         does anyone object if I add the debugger changes to trunk that
>         use the
>         mirror primitives and hence make accurate debugging of proxies
>         possible?
>         The downside of doing this is that the debugger will be broken on
>         older VMs.
>
>
>     It should be possible to write the mirror prims relatively safely, e.g.:
>
>     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>
>             anIndex <= (self objectClass: anObject) instSize
>                     ifTrue:["Assume mirror primitives are missing"
>                             ^anObject instVarAt: index]
>                     ifFalse:["Access beyond fixed variables."
>                             ^self object: anObject basicAt: anIndex -
>     (self objectClass: anObject) instSize].
>
>
> That's a good idea.  Alas it doesn't work because the primitives won't
> fail on the older VMs.  Note that the same primitive is used for
> instVarAt: and object:instVarAt: (and likewise for object:instVarAt:put:
> & objectClass: etc).  The difference is that in the older VM the prims
> assume a fixed argument count and only pop that many objects from the
> stack.  Hence there is the potential of stack overflow in the older VMs.

Okay, then don't use those prims. Simply rename primitiveInstVarAt to
primitiveMirrorInstVarAt, export the latter by name, and use the named
version in cases like the above where the direct usage of prim 73 might
cause a stack overflow. Tada! You can have your cake and eat it, too :-)

Cheers,
   - Andreas