"Martin Kobetic" martin@objectpeople.com wrote...
There was a series of articles in Smalltalk Report (long time ago, obviously) and there is a code in the archive on UIUC (Called LightweightClasses and ObjectDebugging, I believe), which implement breakpoints in some ancient version of VisualWorks. I've got the breakpoints to work in VW5i quite easily, but so far did not get around to make the necessary GUI enhancements. Anyway, I believe it should be fairly straightforward to make it work in Squeak as well. Breakpoints are much better than 'x halt'.
Folks -
I just fetched this code and looked at it. It is quite lean -- a lot of bang for the buck. I include the summary here below. It's 33k, most of which is a specialized browser with a specialized kind of list. The kernel breakpoint and lightwieght class code is very small.
Two questions:
Does anyone know of better code available of a prefereable way of doing this?
Would anyone be interested in porting this code to Squeak?
- Dan ------------------------- NAME ObjectDebugging AUTHOR hinkle@primenet.com FUNCTION Adding LightweightClasses and Breakpoints ST-VERSIONS R4.1 PREREQUISITES None CONFLICTS None known DISTRIBUTION World VERSION 1.0 DATE 25 October 1994 SUMMARY ObjectDebugging Adds two new concepts to the ST-80 programming environment: lightweight classes and breakpoints. Lightweight classes are a new kind of Behavior that allow specific behavior on a per-instance basis. This is useful in many ways, and the main emphasis for this project is in using unique object behavior as an aid in debugging and system exploration. Breakpoints are an easy way of adding 'self halt'-like behavior at the beginning of methods without changing source files. The code in this file is described in the article 'Debugging Objects,' written by myself, Vicki Jones, and Ralph Johnson, which appeared in the July-August 1993 issue (Volume 2, Number 9) of The Smalltalk Report. -- Bob Hinkle "!
"Welcome to objectDebugging.st. This file contains the complete source to add lightweight classes and breakpoint methods to your system. Together these two changes provide new techniques to use while debugging. Since the code is largely uncommented, these prefatory paragraphs serve as documentation for now. The following paragraph is a brief introduction to the purpose of this file, while the one after that explains the interface in more detail."!
"The notion of a lightweight class comes from the desire to be able to change the behavior of a particular object without also changing all the other objects of its class. This can be done by creating a special class for the object, but that's expensive in both time and space, so there's a need for a kind of class that's cheap to create and store--and that's what a lightweight class is. The lightweight class is created between an object and its real class, and so any methods defined in the lightweight class apply only to a singular object. Thus, you can modify the add: method of a particular OrderedCollection, say, without changing all the many other OrderedCollections in the image. One of the changes you can make in a lightweight class (and in regular classes, too) is to put a breakpoint on a method. Breakpointing a method is like adding 'self halt' as its first line, but there are some important differences. First, it's easier to add (and remove) a breakpoint, since it's done by menu rather than by typing. Second, adding/removing breakpoints doesn't affect the various change mechanisms, so the change set and change log don't include trivial changes for putting (and presumably later removing) a halt in a method. Finally, breakpoints are invisible in source code, so when you edit a breakpointed method in a browser (or look at it in the debugger), you see only the normally defined code--the breakpoint itself is transparent. Combining lightweight classes and breakpoints allows you to set breakpoints on methods belonging to an individual object. So it's possible to set a breakpoint on the add: method of one OrderedCollection without bringing the rest of the system to a grinding halt. That kind of debugging is what our object debugging package is for."!
"The interface for all this is (I hope) relatively simple. You can send any object the message 'browseLightweight' to create and edit its lightweight class. (Alternatively, there's also a browseLightweight menu option from any Inspector.) This kind of browsing creates a special Lightweight Class Browser, which looks something like a ClassBrowser, but there are several differences. First, lightweight classes don't have protocols, so rather than seeing methods organized into protocols, you just see a list of all methods for the lightweight class. The method display uses two formatting conventions to convey information: methods that are defined in the lightweight class have their selectors printed in boldface, while those with breakpoints have their selectors preceded by asterisks. Second, in the upper right hand of the browser is a text pane that lets you choose which methods to list--you can either show only methods defined in the lightweight class, or all methods up to some menu-chosen superclass. This option is convenient since it lets you look at methods as defined in a superclass and then alter and accept them in the lightweight class. Finally, the lightweight class browser has an inspector for the object at the bottom, because we believe users will often want to get at objects and their instance variables in the context of object debugging. Adding breakpoints is even easier: every method list now has a menu option called 'breakpoint,' which occurs right above 'move to ...' This option is a toggle switch--if the method is not breakpointed, a breakpoint will be added (and the method's selector will be preceded by an asterisk to indicated this.) If the method is already breakpointed, choosing 'breakpoint' will cause the existing breakpoint to be removed. We envision the browser will be used as follows: a programmer finds there's a problem in a particular method, with some object behaving strangely. So, he or she puts a breakpoint in that method or some previous one where the object is created. When that breakpoint is triggered, the programmer opens a debugger and looks at the problem object in the inspector. Using the browseLightweight menu option, the programmer changes or puts breakpoints on important methods of the object, and then proceeds from the debugger. Now he/she can monitor that one object's behavior and (we hope) discover what the problem is."!
"This code was developed for Smalltalk-80 Release 4.1 for the Macintosh. It should work on earlier releases with work on the interface, and also on compatible versions for other platforms. We're interested in feedback on this package, so please let us know if you have comments, questions, problems, or ideas. In particular, we're interested in whether you find these changes useful for debugging, other features you'd like to see added to this package, other debugging improvements you'd like to see in the Smalltalk environment, and finally any other uses you have for lightweight classes. Please direct any such comments or questions to Bob Hinkle at hinkle@primenet.com."!
Dan Ingalls wrote:
I just fetched this code and looked at it. It is quite lean -- a lot of bang for the buck. I include the summary here below. It's 33k, most of which is a specialized browser with a specialized kind of list. The kernel breakpoint and lightwieght class code is very small.
Two questions:
Does anyone know of better code available of a prefereable way of doing this?
I started on a breakpoint package a while ago which would allow to insert breakpoints anywhere in a method by modifying the parse tree at the selected location in the source string. Never got around to finish it though, but I will dig out the source.
Michael
On Wed, Apr 19, 2000 at 03:57:27PM -0700, Dan Ingalls wrote:
Does anyone know of better code available of a prefereable way of doing this?
ST/X has a similar but more powerfull Breakpoint-system:
With the "MessageTracer" it is possible to wrap methods with blocks that are evaluated on entry or exit of the wrapped method.
MassageTracer allows both class-based and object-based method-wrapping. The normal Behaviour-hierarchy is used for building special classes, no "lightwight" classes are used.
Method-based:
MessageTracer wrapMethod:aMethod onEntry:entryBlock onExit:exitBlock
Object-based:
MessageTracer wrap:anObject selector:aSelector onEntry:entryBlock onExit:exitBlock
MessageTraver provides many predefined Entry/Exit-Blocks and shortcuts: (breakpointing, tracing, timing, memory-usage, modifications)
BreakPoint on Selector:
MessageTracer trap:anObject selector:aSelector
A trace is installed by:
MessageTracer trace:anObject selector:aSelector
this arranges that a trace message is printed to the standard error output (Stderr), both upon entry and exit to/from the method.
BreakPoint when an instancevariable is changed:
MessageTracer trapModificationsIn:anObject
MethodWrapping is a very powerfull tool, e.g. it can be used for conditional Breakpointing:
|p|
p := Point new. MessageTracer wrap:p selector:#x: onEntry:[:con | (con args at:1) > 5 ifTrue:[ Debugger enter:con withMessage:'hit breakPoint; arg > 5' ] ] onExit:nil.
p x:4. "nothing happens" p x:-1. "nothing happens." p x:10. "bummm"
Or for counting method-invocations:
Smalltalk at:#MyCount put:0 .
MessageTracer wrapMethod:(Float compiledMethodAt:#+) onEntry:[:con | MyCount := MyCount + 1] onExit:[:con :ret | ].
All wrapped methods are removed with
MessageTracer unwrapAllMethods
-- Marcus Denker marcus@ira.uka.de phone@home:(0721)614235 @work:(0721)608-2749
squeak-dev@lists.squeakfoundation.org