Topaz can maintain up to eight simultaneous GemStone Smalltalk call stacks that provide information about the GemStone state of execution. Each call stack consists of a linked list of method or block contexts. Topaz provides debugging commands that enable you to:
This chapter introduces you to the Topaz debugging commands and provides some examples. For a detailed description of each of these commands, see Chapter 3.
For the purpose of determining exactly where a step will go during debugging, a GemStone Smalltalk method can be decomposed into step points. The locations of step points also determine where breakpoints can be set, although not all step points are legal for breakpoints.
Generally, step points correspond to the message selector and, within the method, message-sends, assignments, and returns of nonatomic objects. Compiler optimizations, however, may occasionally result in a different, nonintuitive step point, particularly in a loop.
The Topaz list steps method: command lists the source code of a given instance method and displays all step points (allowable breakpoints) in that source code.
topaz 1> set class Dictionary
topaz 1> list steps method: removeKey:ifAbsent:
removeKey: aKey ifAbsent: aBlock
* ^^ 1,2 *******
"Removes the Association with key equal to aKey from the receiver and returns
the value of that Association. If no Association is present with key
equal to aKey, evaluates the zero-argument block aBlock and returns the
result of that evaluation."
| anAssoc |
anAssoc:= self removeKey: aKey otherwise: nil .
* ^4 ^3 *******
anAssoc == nil ifTrue:[
* ^5 *******
aBlock == nil ifTrue:[^ nil ].
* ^6 ^7 *******
^aBlock value
* ^9 ^8 *******
].
^ anAssoc value
* ^11 ^10 *******
As shown here, the position of each method step point is marked with a caret (^) and a number.
If you use the Topaz step command to step through this method, the first step stops execution at the beginning of the method. The next step takes you to the point where removeKey:otherwise: is about to be sent to self. Stepping again would execute that message-send and halt execution at the point where anAssoc is about to be assigned. Another step would cause that assignment to be happen, and then halt execution just before the message == is sent to anAssoc.
The call stack becomes active, and the debugging commands become accessible, when you execute GemStone Smalltalk code containing a breakpoint (as well as when you encounter an error).
You can use the break command to set a method breakpoint at a particular step point within a method.
While you can set a breakpoint on any method, methods with optimized selectors, such as Boolean>>ifTrue: never hit the break points unless you invoke them with perform: or one of the GciPerform... functions, because sends of special selectors are optimized by the compiler. Note that in the step points listed above for Dictionary >> removeKey:ifAbsent:, above, there are no step points on ifTrue:.
You can use the break command to establish method breakpoints within your GemStone Smalltalk code:
break aClassName >> aSelector [@ stepNumber]
break aClassName class >> aSelector [@ stepNumber]
topaz 1> break GsFile class >> openRead: @ 2
Establishes a breakpoint at step point 2 of the class method openRead: for GsFile. There are a number of ways to specify the specific class and method: see BREAK for details.
The break list command allows you to see all breakpoints set
topaz 1> break list
1: GsFile >> nextLine @ 1
2: GsFile class >> openRead: @ 2
3: String >> < @ 2
In the break list result, each breakpoint is identified by a break index. To disable a breakpoint, supply that break index as the single argument to the break disable command:
topaz 1> break disable 2
topaz 1> break list
1: GsFile >> nextLine @ 1
2: GsFile class >> openRead: @ -2 (disabled)
3: String >> < @ 2
A similar command line reenables the break point:
topaz 1> break enable 2
To delete a single breakpoint, supply that break index as the argument to the break delete command:
topaz 1> break delete 2
To delete all currently set breakpoints, type the following command:
topaz 1> break delete all
When you execute the code on which you have enabled a breakpoint, execution pauses. For example, if we put a breakpoint on the setter method for Animal’s instance variable #name:
topaz 1 > break Animal >> name:
topaz 1 > run
Animal new name: 'Dog'
%
a Breakpoint occurred (error 6005), Method breakpoint encountered.
1 1 Animal >> name: @1 line 1
You can display all of the contexts in the active call stack by issuing the where, stk or stack commands with no arguments. The where and stk command display a summary call stack, with one line for each context. Use the stack command to display method arguments and temporaries. When using the stack command, the volume of output displayed is controlled by the current level setting.
This is an example of the where summary:
topaz 1> where
==> 1 Animal >> name: @1 line 1
2 Executed Code @3 line 1
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
With display oops active, the where command provides more detail for each frame:
topaz 1> display oops
topaz 1> where
==> 1 Animal >> name: @1 line 1 [methId 25534209]
2 Executed Code @3 line 1 [methId 25504513]
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1 [methId 4912641]
[GsProcess 27551489]
Using the stack command provides additional information about the instance and temporary variable names and values for each context. With level 0 (the default), only the variable values themselves are displayed. This example is with display oops.
topaz 1> stack
==> 1 Animal >> name: @1 line 1 [methId 25534209]
receiver [25517313 sz:3 cls: 27556097 Animal] a Animal
name [20 sz:0 cls: 76289 UndefinedObject] nil
favoriteFood [20 sz:0 cls: 76289 UndefinedObject] nil
habitat [20 sz:0 cls: 76289 UndefinedObject] nil
newValue [25481729 sz:3 cls: 74753 String] Dog
2 Executed Code @3 line 1 [methId 25504513]
receiver [20 sz:0 cls: 76289 UndefinedObject] nil
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1 [methId 4912641]
receiver [20 sz:0 cls: 76289 UndefinedObject] nil
With level 1, or higher levels, the variables for each instance variable is included in the display for stack. For example, with omit oops:
topaz 1> omit oops
topaz 1> level 1
topaz 1> stack
==> 1 Animal >> name: @1 line 1
receiver a Animal
name nil
favoriteFood nil
habitat nil
newValue Dog
2 Executed Code @3 line 1
receiver nil
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
receiver nil
The display of each context includes:
The display is governed by the setting of other Topaz commands such as limit, level, and display or omit.
When GemStone Smalltalk encounters a breakpoint during normal execution, Topaz halts and waits for your reply. Topaz provides commands for continuing execution, and for stepping into and over message-sends.
continue
Tells GemStone Smalltalk to continue execution from the context at the top of the stack, if possible. If execution halts because of an authorization error, for example, then the virtual machine can’t continue. As an option, the continue command can replace the value on the top of the stack with another object before it attempts to continue execution.
step over
Tells GemStone Smalltalk to advance execution to the next step point (message-send, assignment, etc.) in the active context or its caller, and halt. The active context is indicated by the ==> in the stack; it is the context specified by the last frame, up, down or another command. Initially it is the top of the stack (the first context in the list).
step into
Tells GemStone Smalltalk to advance execution to the next step point (message-send, assignment, etc.) and halt. If the current step point is a message-send, then execution will halt at the first step point within the method invoked by that message-send.
Notice how this differs from step over; if the next message in the context contains step points itself, execution halts at the first of those step points. That is, the virtual machine “steps into” the new method instead of silently executing that method’s instructions and halting after the method has completed. The next step over command will then take place within the context of the new method.
The Topaz temporary command lets you examine or modify the values of temporaries in the active context. If, for example, the method under inspection had a temporary variable named count, that currently had a value of 5, you could obtain its value by typing temporary and the variable name:
topaz 1> temporary count5
Similarly, you can use the temporary command to assign a new value to a temporary variable:
topaz 1> temporary count 8
For example, the following code sets a breakpoint, executes code, views and updates the value of a temporary variable, then continues execution to return the results of the code; which has been changed during debugging.
topaz 1> break classmethod String withAll:
topaz 1> run
String withAll: 'abc'
%
a Breakpoint occurred (error 6005), Method breakpoint encountered.
1 String class >> withAll: @1 line 1
topaz 1> stack
==> 1 String class >> withAll: @1 line 1
receiver String
aString abc
2 Executed Code @2 line 1
receiver nil
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
receiver nil
topaz 1> temporary
aString abc
topaz 1> temporary aString 'xyz'
topaz 1> stack
==> 1 String class >> withAll: @1 line 1
receiver String
aString xyz
2 Executed Code @2 line 1
receiver nil
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
receiver nil
topaz 1> continue
xyz
The Topaz commands frame, up, and down, as well as stack up, stack down, and stack scope, let you redefine the active context (used by the temporary, stack, and list commands) within the current call stack. Consider the call stack we examined earlier, with level 0 and omit oops:
topaz 1> stack
==> 1 Animal >> name: @1 line 1
receiver anAnimal
newValue Dog
2 Executed Code @3 line 1
receiver nil
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
receiver nil
The active context is indicated by ==>. You can also show the active context by using the frame command with no arguments:
topaz 1> frame1 Animal >> name: @1 line 1
receiver anAnimal
newValue Dog
The following command selects the caller of this context as the new active context:
topaz 1> frame 22 Executed Code @3 line 1
receiver nil
Now confirm that Topaz redefined the active context:
topaz 1> where
1 Animal >> name: @1 line 1
==> 2 Executed Code @3 line 1
3 UndefinedObject (GsNMethod class) >> _gsReturnToC @1 line 1
You can also use up and down commands to make a different frame the active context.
By default, when you continue executing code and encounter another breakpoint, the original call stack is lost.
The Topaz command stack save lets you retain the previous stack. This needs to be invoked for each stack you want to save.
The Topaz command stack all lets you display your list of saved call stacks. This display includes the top context of every call stack:
topaz 1> stack all 0: 1 Animal >> habitat @1 line 1
1: 1 AbstractException >> _signalWith: @6 line 25
*2: 1 Executed Code @3 line 1
The asterisk (*) indicates the active call stack, if one exists. If there are no saved stacks, a message to that effect is displayed.
When you type the stack change command, Topaz sets the active call stack to the call stack indicated by the integer in the stack all command output, and displays the newly selected call stack:
topaz 1> stack change 1
Stack 1 , GsProcess 27447553
1 AbstractException >> _signalWith: @6 line 25