SmallSense__Manager.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Tue, 22 Oct 2013 17:29:00 +0100
changeset 138 3355e5292e1d
parent 111 2d880f47cfff
child 174 3e08d765d86f
permissions -rw-r--r--
Rescan instances to infer instvar types time to time. This is code by maintaining a global sequence number in manager and keeping value of that sequence number at the time of updating ClassInfo. Then, if the current sequence number is much higher than existing info's saved number, instances are scanned again and class info is updated accordingly.

"{ Package: 'jv:smallsense' }"

"{ NameSpace: SmallSense }"

Object subclass:#Manager
	instanceVariableNames:'classes accessLock updater seqno'
	classVariableNames:'Instance'
	poolDictionaries:''
	category:'SmallSense-Smalltalk-Types-Info'
!


!Manager class methodsFor:'instance creation'!

flush
    "flushes the cached singleton"

    Instance := nil

    "
     self flushSingleton
    "

    "Created: / 16-12-2011 / 01:37:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

flushSingleton
    "flushes the cached singleton"

    Instance := nil

    "
     self flushSingleton
    "
!

instance
    "returns a singleton"

    Instance isNil ifTrue:[
        Instance := self basicNew initialize.
    ].
    ^ Instance.

    "Created: / 27-11-2011 / 15:30:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

new
    "returns a singleton"

    ^ self instance.

    "Modified: / 27-11-2011 / 15:30:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'accessing'!

infoForClass: class

    | info |

    accessLock critical:[
        info := self basicInfoForClass: class.
    ].
    ^info

    "Created: / 27-11-2011 / 16:15:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

infoForClassOrNil: class

    ^classes at: class name ifAbsent: nil

    "Created: / 27-11-2011 / 17:15:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'accessing-private'!

basicInfoForClass: class

    class isNil ifTrue:[^nil].

    ^classes at: class name ifAbsentPut:[
        ClassInfo new
            setManager: self
            className: class name
    ].

    "Created: / 27-11-2011 / 16:47:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'change & update'!

update:what with:param from:sender
    "Invoked when an object that I depend upon sends a change notification."

    UserPreferences current smallSenseBackgroundTypingEnabled ifFalse:[ ^ self ].

    sender ~~ Smalltalk ifTrue:[
        super update:what with:param from:sender.
        ^self.
    ].

    what == #methodInClass ifTrue:[
        self updateInfoForMethod: (param first >> param second).
        ^self.
    ].
    

"/    Transcript show: 'SmallSense: Smalltalk changed: ', what , ' with: ', param printString.

    "Modified: / 04-02-2012 / 22:30:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'initialization'!

initialize
    "Invoked when a new instance is created."

    classes := Dictionary new.
    accessLock := Semaphore forMutualExclusion.
    updater := BackgroundQueueProcessingJob 
                    named: 'SmallSense background updater' 
                    on: [:classOrMethod|self delayedUpdateInfoForClassOrMethod: classOrMethod].
    updater priority: Processor userBackgroundPriority - 1.

    UserPreferences current smallSenseEnabled ifTrue:[
        Smalltalk addDependent: self.
    ].
    seqno := 0

    "Modified: / 22-10-2013 / 10:56:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'updating'!

updateInfoForClass: class

    | info |

    class programmingLanguage isSmalltalk ifFalse:[ ^ self ].
    info := self infoForClassOrNil: class.
    (info isNil or:[(info seqno ? 0) < (seqno - 100)]) ifTrue:[
        updater add: class
    ].
    seqno := seqno == SmallInteger maxVal ifTrue: [1] ifFalse:[seqno + 1]

    "Created: / 27-11-2011 / 17:46:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 22-10-2013 / 11:38:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

updateInfoForMethod: method

    | info |

    method programmingLanguage isSmalltalk ifFalse:[ ^ self ].
    info := self basicInfoForClass: method mclass.
    info isNil ifTrue:[
        updater add: method mclass
    ] ifFalse:[
        updater add: method
    ]

    "Created: / 28-11-2011 / 19:30:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager methodsFor:'updating-delayed'!

delayedUpdateInfoForClass: class

    | superclass info instVarNames instVarTypes nprobed |

    superclass := class superclass.
    superclass notNil ifTrue:[self updateInfoForClass: superclass].
    info := self infoForClass: class.
    info seqno: seqno.
    instVarNames := class allInstVarNames.
    instVarTypes := instVarNames collect: [:instvar | info infoForInstvar: instvar ]. 
    class methodsDo:[:mthd|updater add:mthd].

    nprobed := 0.
    class allInstancesDo: [:instance |
        instVarTypes withIndexDo: [:instVarType :i | 
            instVarType union: ((Type withClass: (instance instVarAt: i) class) type trustfullness: 70). 
        ].
        nprobed := nprobed + 1.
        nprobed > 100 ifTrue:[
            "/ Probe at most 100 instancess
            ^ self
        ].
    ].

    "Created: / 27-11-2011 / 18:04:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 22-10-2013 / 11:14:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateInfoForClassOrMethod: classOrMethod

    classOrMethod isBehavior ifTrue:[
       self delayedUpdateInfoForClass: classOrMethod.
    ].
    classOrMethod isMethod ifTrue:[
       self delayedUpdateInfoForMethod: classOrMethod.
    ]

    "Created: / 27-11-2011 / 18:01:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

delayedUpdateInfoForMethod: method

    | inferencer |

    method mclass isNil ifTrue:["Obsolete method" ^ self ].
    method mclass programmingLanguage isSmalltalk ifFalse: [ ^ self ].
"/    Transcript showCR: 'SmallSense: updating info for: ', method printString.
    inferencer := SmalltalkInferencer forMethod: method.
    inferencer process.

    "Created: / 27-11-2011 / 18:06:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 26-08-2013 / 10:20:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!Manager class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
!

version_SVN
    ^ '$Id: SmallSenseManager.st 7984 2012-04-21 08:36:11Z vranyj1 $'
! !