Variable objects: preserve the identity of `GDBFrame` and `GDBVariable` objects
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 15 Feb 2018 08:46:03 +0000
changeset 103 56bf65352505
parent 102 d573a3b2abe2
child 104 4add55336dfe
Variable objects: preserve the identity of `GDBFrame` and `GDBVariable` objects ...across running / stopped cycle. This means that if given frame remains on the stack between top stops of a program, the `GDBFrame` instance that represents it would be the same (identical).
GDBFrame.st
GDBMI_var_info_expression.st
GDBMI_var_info_path_expression.st
GDBThread.st
GDBTransientDataHolder.st
GDBVariableObject.st
Make.proto
Make.spec
bc.mak
libInit.cc
tests/GDBDebuggerTestsR.st
tests/GDBTransientDataHolderTests.st
--- a/GDBFrame.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBFrame.st	Thu Feb 15 08:46:03 2018 +0000
@@ -20,7 +20,7 @@
 
 "{ NameSpace: Smalltalk }"
 
-GDBTransientObject subclass:#GDBFrame
+GDBDebuggerObject subclass:#GDBFrame
 	instanceVariableNames:'thread level addr func file fullname line from variables'
 	classVariableNames:''
 	poolDictionaries:''
@@ -64,6 +64,7 @@
         yourself
 
     "Created: / 16-09-2014 / 23:59:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-02-2018 / 08:27:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBFrame methodsFor:'accessing'!
@@ -121,6 +122,32 @@
     "Modified: / 17-11-2017 / 20:22:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!GDBFrame methodsFor:'initialization'!
+
+setAddr: aString
+    addr := aString
+
+    "Created: / 31-01-2018 / 09:50:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setLevel: anInteger
+    level := anInteger
+
+    "Created: / 15-02-2018 / 08:34:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setLine: anInteger
+    line := anInteger
+
+    "Created: / 01-02-2018 / 10:09:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setThread: aGDBThread
+    thread := aGDBThread
+
+    "Created: / 30-01-2018 / 15:56:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !GDBFrame methodsFor:'printing & storing'!
 
 displayString
@@ -171,6 +198,28 @@
     "Modified: / 27-02-2015 / 15:21:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!GDBFrame methodsFor:'private'!
+
+ensureIsValid
+    self isValid ifFalse:[
+        (GDBInvalidObject newException)
+            parameter:self;
+            messageText:'Invalid (obsolete) object';
+            raise.
+    ].
+
+    "Created: / 07-09-2014 / 23:08:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 30-01-2018 / 17:51:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBFrame methodsFor:'testing'!
+
+isValid
+    ^ addr notNil
+
+    "Modified: / 30-01-2018 / 15:58:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !GDBFrame class methodsFor:'documentation'!
 
 version_HG
--- a/GDBMI_var_info_expression.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBMI_var_info_expression.st	Thu Feb 15 08:46:03 2018 +0000
@@ -87,3 +87,10 @@
 	^ 'var-info-expression'
 ! !
 
+!GDBMI_var_info_expression class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/GDBMI_var_info_path_expression.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBMI_var_info_path_expression.st	Thu Feb 15 08:46:03 2018 +0000
@@ -86,3 +86,10 @@
 	^ 'var-info-path-expression'
 ! !
 
+!GDBMI_var_info_path_expression class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/GDBThread.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBThread.st	Thu Feb 15 08:46:03 2018 +0000
@@ -95,23 +95,65 @@
 stack
     self ensureIsStopped.
     stack isNil ifTrue:[
-        stack := GDBTransientDataHolder debugger: debugger factory:[ 
-            | result depth frames |
+        stack := GDBTransientDataHolder debugger: debugger factory:[ :old | 
+            | result depth new oldFrameIndex oldFrame newFrameIndex newFrame  |
             result := debugger send: (GDBMI_stack_info_depth new arguments: (Array with: '--thread' with: id with: 100)).
             depth := result propertyAt: #depth.
             result := debugger send: (GDBMI_stack_list_frames new arguments: (Array with:  '--thread' with: id with: 0 with: depth - 1 )).
-            frames := result propertyAt: #stack.
-            frames do:[:each | 
-                each debugger: debugger.
-                each propertyAt: #thread put: self 
+            new := result propertyAt: #stack.
+
+            "/ Now, walk from the bottom of the stack (the least recent frame) and
+            "/ ipdate `new` array with frames from `old` array to preserve the
+            "/ identity.
+            newFrameIndex := new size.
+            oldFrameIndex := old size.
+            [ newFrameIndex > 0 and:[ oldFrameIndex > 0 ] ] whileTrue:[ 
+                newFrame := new at: newFrameIndex.
+                oldFrame := old at: oldFrameIndex.
+                "/ If frame addrs matches, both frames really represent the same thing so
+                "/ just replace the 'new' frame with the 'old'.
+                newFrame addr = oldFrame addr ifTrue:[ 
+                    "/ OK, the two frames are really the same thing
+                    oldFrame setLevel: newFrame level.
+                    new at: newFrameIndex put: (old at: oldFrameIndex).
+                    newFrameIndex := newFrameIndex - 1.
+                    oldFrameIndex := oldFrameIndex - 1.
+                ] ifFalse:[ 
+                    "/ No, frame pc differs. This is the first time they differ so
+                    "/ it could be the same frame just on different PC (since PC of
+                    "/ caller did not change). Check, if function names matches,
+                    "/ if so, update the frame and exit the loop. If not, just exit
+                    "/ the loop.
+                    oldFrame func = newFrame func ifTrue:[ 
+                        "/ Update the frame...
+                        oldFrame setAddr: newFrame addr.
+                        oldFrame setLine: newFrame line.
+                        oldFrame setLevel: newFrame level.
+                        new at: newFrameIndex put: (old at: oldFrameIndex).
+
+                        "/ Note, that we need to presetve the newFrameIndex value, it's
+                        "/ used below!!
+                        newFrameIndex := newFrameIndex - 1.
+                    ].
+                    "/ Terminate the loop, see the condition above.
+                    oldFrameIndex := 0. 
+                ].
             ].
-            frames
+            "/ For the remaining really new frames, set the debugger
+            "/ and the thread.
+            [ newFrameIndex > 0 ] whileTrue:[ 
+                newFrame := new at: newFrameIndex.
+                newFrame setDebugger: debugger.
+                newFrame setThread: self.
+                newFrameIndex := newFrameIndex - 1.
+            ].
+            new
         ].
     ].
     ^ stack value
 
     "Created: / 09-09-2014 / 00:02:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 17-11-2017 / 20:21:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-02-2018 / 08:41:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 status
--- a/GDBTransientDataHolder.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBTransientDataHolder.st	Thu Feb 15 08:46:03 2018 +0000
@@ -73,19 +73,20 @@
 !GDBTransientDataHolder methodsFor:'accessing'!
 
 value
-    | token val |
+    | token old new |
     (value ~~ InvalidValue and:[debugger currentInferiorStateSequnceNumber == seqno]) ifTrue:[ 
         ^ value.
     ].
+    old := value == InvalidValue ifTrue:[ nil ] ifFalse:[ value ].
     value := token := Object new.
-    val := factory value.
+    new := factory valueWithOptionalArgument: old.
     value == token ifTrue:[ 
-        self value: val.
+        self value: new.
     ].
     ^ value
 
     "Created: / 17-09-2014 / 22:06:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 30-01-2018 / 09:06:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 31-01-2018 / 09:28:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 value: anObject
--- a/GDBVariableObject.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/GDBVariableObject.st	Thu Feb 15 08:46:03 2018 +0000
@@ -172,6 +172,7 @@
     "Created: / 27-01-2018 / 22:54:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+
 !GDBVariableObject methodsFor:'printing & storing'!
 
 printOn:aStream
--- a/Make.proto	Mon Jan 29 10:21:03 2018 +0000
+++ b/Make.proto	Thu Feb 15 08:46:03 2018 +0000
@@ -178,6 +178,7 @@
 $(OUTDIR)GDBEventSetEvent.$(O) GDBEventSetEvent.$(C) GDBEventSetEvent.$(H): GDBEventSetEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBInternalEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBExecutionEvent.$(O) GDBExecutionEvent.$(C) GDBExecutionEvent.$(H): GDBExecutionEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBExitEvent.$(O) GDBExitEvent.$(C) GDBExitEvent.$(H): GDBExitEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBInternalEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)GDBFrame.$(O) GDBFrame.$(C) GDBFrame.$(H): GDBFrame.st $(INCLUDE_TOP)/jv/libgdbs/GDBDebuggerObject.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLogOutputEvent.$(O) GDBLogOutputEvent.$(C) GDBLogOutputEvent.$(H): GDBLogOutputEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBStreamOutputEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBMI_ada_task_info.$(O) GDBMI_ada_task_info.$(C) GDBMI_ada_task_info.$(H): GDBMI_ada_task_info.st $(INCLUDE_TOP)/jv/libgdbs/GDBCommand.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBMICommand.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBMI_add_inferior.$(O) GDBMI_add_inferior.$(C) GDBMI_add_inferior.$(H): GDBMI_add_inferior.st $(INCLUDE_TOP)/jv/libgdbs/GDBCommand.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBMICommand.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
@@ -302,7 +303,6 @@
 $(OUTDIR)GDBCmdParamChangedEvent.$(O) GDBCmdParamChangedEvent.$(C) GDBCmdParamChangedEvent.$(H): GDBCmdParamChangedEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBNotificationEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBEventSetProcessingFinished.$(O) GDBEventSetProcessingFinished.$(C) GDBEventSetProcessingFinished.$(H): GDBEventSetProcessingFinished.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEventSetEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBInternalEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBEventSetProcessingStarted.$(O) GDBEventSetProcessingStarted.$(C) GDBEventSetProcessingStarted.$(H): GDBEventSetProcessingStarted.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEventSetEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBInternalEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
-$(OUTDIR)GDBFrame.$(O) GDBFrame.$(C) GDBFrame.$(H): GDBFrame.st $(INCLUDE_TOP)/jv/libgdbs/GDBDebuggerObject.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBTransientObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLibraryLoadedEvent.$(O) GDBLibraryLoadedEvent.$(C) GDBLibraryLoadedEvent.$(H): GDBLibraryLoadedEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBNotificationEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLibraryUnloadedEvent.$(O) GDBLibraryUnloadedEvent.$(C) GDBLibraryUnloadedEvent.$(H): GDBLibraryUnloadedEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBNotificationEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)GDBRunningEvent.$(O) GDBRunningEvent.$(C) GDBRunningEvent.$(H): GDBRunningEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBExecutionEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
--- a/Make.spec	Mon Jan 29 10:21:03 2018 +0000
+++ b/Make.spec	Thu Feb 15 08:46:03 2018 +0000
@@ -102,6 +102,7 @@
 	GDBEventSetEvent \
 	GDBExecutionEvent \
 	GDBExitEvent \
+	GDBFrame \
 	GDBLogOutputEvent \
 	GDBMI_ada_task_info \
 	GDBMI_add_inferior \
@@ -226,7 +227,6 @@
 	GDBCmdParamChangedEvent \
 	GDBEventSetProcessingFinished \
 	GDBEventSetProcessingStarted \
-	GDBFrame \
 	GDBLibraryLoadedEvent \
 	GDBLibraryUnloadedEvent \
 	GDBRunningEvent \
@@ -298,6 +298,7 @@
     $(OUTDIR)GDBEventSetEvent.$(O) \
     $(OUTDIR)GDBExecutionEvent.$(O) \
     $(OUTDIR)GDBExitEvent.$(O) \
+    $(OUTDIR)GDBFrame.$(O) \
     $(OUTDIR)GDBLogOutputEvent.$(O) \
     $(OUTDIR)GDBMI_ada_task_info.$(O) \
     $(OUTDIR)GDBMI_add_inferior.$(O) \
@@ -422,7 +423,6 @@
     $(OUTDIR)GDBCmdParamChangedEvent.$(O) \
     $(OUTDIR)GDBEventSetProcessingFinished.$(O) \
     $(OUTDIR)GDBEventSetProcessingStarted.$(O) \
-    $(OUTDIR)GDBFrame.$(O) \
     $(OUTDIR)GDBLibraryLoadedEvent.$(O) \
     $(OUTDIR)GDBLibraryUnloadedEvent.$(O) \
     $(OUTDIR)GDBRunningEvent.$(O) \
--- a/bc.mak	Mon Jan 29 10:21:03 2018 +0000
+++ b/bc.mak	Thu Feb 15 08:46:03 2018 +0000
@@ -125,6 +125,7 @@
 $(OUTDIR)GDBEventSetEvent.$(O) GDBEventSetEvent.$(C) GDBEventSetEvent.$(H): GDBEventSetEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBInternalEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBExecutionEvent.$(O) GDBExecutionEvent.$(C) GDBExecutionEvent.$(H): GDBExecutionEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBExitEvent.$(O) GDBExitEvent.$(C) GDBExitEvent.$(H): GDBExitEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBInternalEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)GDBFrame.$(O) GDBFrame.$(C) GDBFrame.$(H): GDBFrame.st $(INCLUDE_TOP)\jv\libgdbs\GDBDebuggerObject.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLogOutputEvent.$(O) GDBLogOutputEvent.$(C) GDBLogOutputEvent.$(H): GDBLogOutputEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBStreamOutputEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBMI_ada_task_info.$(O) GDBMI_ada_task_info.$(C) GDBMI_ada_task_info.$(H): GDBMI_ada_task_info.st $(INCLUDE_TOP)\jv\libgdbs\GDBCommand.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBMICommand.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBMI_add_inferior.$(O) GDBMI_add_inferior.$(C) GDBMI_add_inferior.$(H): GDBMI_add_inferior.st $(INCLUDE_TOP)\jv\libgdbs\GDBCommand.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBMICommand.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
@@ -249,7 +250,6 @@
 $(OUTDIR)GDBCmdParamChangedEvent.$(O) GDBCmdParamChangedEvent.$(C) GDBCmdParamChangedEvent.$(H): GDBCmdParamChangedEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBNotificationEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBEventSetProcessingFinished.$(O) GDBEventSetProcessingFinished.$(C) GDBEventSetProcessingFinished.$(H): GDBEventSetProcessingFinished.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEventSetEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBInternalEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBEventSetProcessingStarted.$(O) GDBEventSetProcessingStarted.$(C) GDBEventSetProcessingStarted.$(H): GDBEventSetProcessingStarted.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEventSetEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBInternalEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
-$(OUTDIR)GDBFrame.$(O) GDBFrame.$(C) GDBFrame.$(H): GDBFrame.st $(INCLUDE_TOP)\jv\libgdbs\GDBDebuggerObject.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBTransientObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLibraryLoadedEvent.$(O) GDBLibraryLoadedEvent.$(C) GDBLibraryLoadedEvent.$(H): GDBLibraryLoadedEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBNotificationEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBLibraryUnloadedEvent.$(O) GDBLibraryUnloadedEvent.$(C) GDBLibraryUnloadedEvent.$(H): GDBLibraryUnloadedEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBNotificationEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)GDBRunningEvent.$(O) GDBRunningEvent.$(C) GDBRunningEvent.$(H): GDBRunningEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBExecutionEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
--- a/libInit.cc	Mon Jan 29 10:21:03 2018 +0000
+++ b/libInit.cc	Thu Feb 15 08:46:03 2018 +0000
@@ -67,6 +67,7 @@
 extern void _GDBEventSetEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBExecutionEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBExitEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
+extern void _GDBFrame_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBLogOutputEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBMI_137ada_137task_137info_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBMI_137add_137inferior_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
@@ -191,7 +192,6 @@
 extern void _GDBCmdParamChangedEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBEventSetProcessingFinished_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBEventSetProcessingStarted_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
-extern void _GDBFrame_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBLibraryLoadedEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBLibraryUnloadedEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
 extern void _GDBRunningEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
@@ -272,6 +272,7 @@
     _GDBEventSetEvent_Init(pass,__pRT__,snd);
     _GDBExecutionEvent_Init(pass,__pRT__,snd);
     _GDBExitEvent_Init(pass,__pRT__,snd);
+    _GDBFrame_Init(pass,__pRT__,snd);
     _GDBLogOutputEvent_Init(pass,__pRT__,snd);
     _GDBMI_137ada_137task_137info_Init(pass,__pRT__,snd);
     _GDBMI_137add_137inferior_Init(pass,__pRT__,snd);
@@ -396,7 +397,6 @@
     _GDBCmdParamChangedEvent_Init(pass,__pRT__,snd);
     _GDBEventSetProcessingFinished_Init(pass,__pRT__,snd);
     _GDBEventSetProcessingStarted_Init(pass,__pRT__,snd);
-    _GDBFrame_Init(pass,__pRT__,snd);
     _GDBLibraryLoadedEvent_Init(pass,__pRT__,snd);
     _GDBLibraryUnloadedEvent_Init(pass,__pRT__,snd);
     _GDBRunningEvent_Init(pass,__pRT__,snd);
--- a/tests/GDBDebuggerTestsR.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/tests/GDBDebuggerTestsR.st	Thu Feb 15 08:46:03 2018 +0000
@@ -331,6 +331,49 @@
     "Modified (format): / 11-07-2017 / 23:31:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+test_stack_01
+    "Tests that stack frames object are preserved amonh run/top cycles
+     if they 're still valid"
+
+    | stack1 stack2 |
+
+    debugger := GDBDebugger new.
+    self assert: debugger isConnected.
+    debugger executable: GDBDebuggeesResource current binaryFactorial1.
+    debugger send: 'b factorial'.
+    debugger send: 'r' andWaitFor: GDBStoppedEvent.
+
+    stack1 := debugger selectedInferior threads first stack.
+    debugger send: 'c' andWaitFor: GDBStoppedEvent.
+    stack2 := debugger selectedInferior threads first stack.
+    self assert: stack1 size == 2.
+    self assert: stack2 size == 3.
+    self assert: stack1 first  == stack2 second.
+    self assert: stack1 second == stack2 third.
+    self assert: stack2 first line == 4.
+    self assert: stack2 second line == 7.
+
+    stack1 := debugger selectedInferior threads first stack.
+    debugger send: 'c' andWaitFor: GDBStoppedEvent.
+    stack2 := debugger selectedInferior threads first stack.
+    self assert: stack1 size == 3.
+    self assert: stack2 size == 4.
+    self assert: stack1 first  == stack2 second.
+    self assert: stack1 second == stack2 third.
+    self assert: stack1 third == stack2 fourth.
+    self assert: stack2 first line == 4.
+    self assert: stack2 second line == 7.
+    self assert: stack2 third line == 7.
+
+
+    debugger send: 'd'.
+    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
+    debugger send: 'quit' andWait: false.
+
+    "Created: / 30-01-2018 / 15:54:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-02-2018 / 21:04:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 test_variables_01
     | variables d |
 
@@ -378,6 +421,8 @@
     debugger send: 'quit' andWait: false.
 
     "Created: / 30-01-2018 / 10:27:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+
+
 ! !
 
 !GDBDebuggerTestsR class methodsFor:'documentation'!
--- a/tests/GDBTransientDataHolderTests.st	Mon Jan 29 10:21:03 2018 +0000
+++ b/tests/GDBTransientDataHolderTests.st	Thu Feb 15 08:46:03 2018 +0000
@@ -124,6 +124,41 @@
     self assert: evaluated.
 
     "Created: / 30-01-2018 / 09:08:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_03
+    | holder evaluated |
+
+    evaluated := false.
+    holder := GDBTransientDataHolder debugger: self factory: [ :old | evaluated := true. old notNil ifTrue:[ old + 1 ] ifFalse: [ 100 ] ].
+
+    self assert: holder value == 100.
+    self assert: evaluated.
+
+    "/ factory should not be evaluated and old value should
+    "/ bre returned since sequence number has not changed.
+    evaluated := false. 
+    self assert: holder value == 100.
+    self assert: evaluated not.
+    self assert: holder value == 100.
+    self assert: evaluated not.
+
+    "/ change the sequence number a check the value has been
+    "/ rreevaluated
+    seqNo := seqNo + 1.
+    evaluated := false. 
+    self assert: holder value == 101.
+    self assert: evaluated.
+
+    "/ factory should not be evaluated and old value should
+    "/ bre returned since sequence number has not changed.
+    evaluated := false. 
+    self assert: holder value == 101.
+    self assert: evaluated not.
+    self assert: holder value == 101.
+    self assert: evaluated not.
+
+    "Created: / 31-01-2018 / 09:26:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !GDBTransientDataHolderTests class methodsFor:'documentation'!