JavaMethodAnalyzer.st
author Claus Gittinger <cg@exept.de>
Wed, 26 Jun 2019 22:06:15 +0200
branchcvs_MAIN
changeset 3917 94088b7097d5
parent 3744 b704ed7274d4
child 3921 1999ba4ed954
permissions -rw-r--r--
#OTHER by cg +bracketStrings

"
 COPYRIGHT (c) 1996-2015 by Claus Gittinger

 New code and modifications done at SWING Research Group [1]:

 COPYRIGHT (c) 2010-2015 by Jan Vrany, Jan Kurs and Marcel Hlopko
                            SWING Research Group, Czech Technical University in Prague

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.

 [1] Code written at SWING Research Group contains a signature
     of one of the above copright owners. For exact set of such code,
     see the differences between this version and version stx:libjava
     as of 1.9.2010
"
"{ Package: 'stx:libjava' }"

"{ NameSpace: Smalltalk }"

JavaByteCodeProcessorAdapter subclass:#JavaMethodAnalyzer
	instanceVariableNames:'fieldsAccessed fieldsRead fieldsWritten staticsAccessed
		staticsRead staticsWritten methodsInvoked refdClasses'
	classVariableNames:''
	poolDictionaries:''
	category:'Languages-Java-Support-Decompiling'
!

!JavaMethodAnalyzer class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1996-2015 by Claus Gittinger

 New code and modifications done at SWING Research Group [1]:

 COPYRIGHT (c) 2010-2015 by Jan Vrany, Jan Kurs and Marcel Hlopko
                            SWING Research Group, Czech Technical University in Prague

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.

 [1] Code written at SWING Research Group contains a signature
     of one of the above copright owners. For exact set of such code,
     see the differences between this version and version stx:libjava
     as of 1.9.2010

"
!

documentation
"
    A helper class to analyze method's bytecode and keep some statistics
    like read/written fields, sent messages, referenced classes...

    [author:]
        Jan Vrany <jan.vrany@fit.cvut.cz>

    [instance variables:]

    [class variables:]

    [see also:]

"
! !

!JavaMethodAnalyzer class methodsFor:'analyzing'!

analyze: aJavaMethod
    "Analyzes the given method and return the analyzer,
     which can be in turn asked for various informstion"

     ^ self new
        process: aJavaMethod 
        receiver: nil
        arguments: (Array new: aJavaMethod javaNumArgs);
        yourself

    "Created: / 30-08-2013 / 13:33:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer methodsFor:'instructions'!

anewarray
    | classRef |

    classRef := constantPool at: self fetchIndex2.
    refdClasses add: classRef.

    "Created: / 09-09-2013 / 12:21:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

getfield
    | fieldRef |

    fieldRef := constantPool at: self fetchIndex2.     
    fieldsRead add: fieldRef.
    fieldsAccessed add: fieldRef.

    "Created: / 30-08-2013 / 13:25:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 05-09-2013 / 16:19:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

getstatic
    | fieldRef |

    fieldRef := constantPool at: self fetchIndex2.     
    staticsRead add: fieldRef.
    staticsAccessed  add: fieldRef.
    refdClasses add: fieldRef classRef.

    "Created: / 05-09-2013 / 16:19:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-09-2013 / 12:16:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

invinterface
    methodsInvoked add: (constantPool at: self fetchBytes2).
    self fetchBytes2  "/ count

    "Created: / 30-08-2013 / 17:05:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 30-08-2013 / 20:28:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

invnonvirt
     methodsInvoked add: (constantPool at: self fetchBytes2)

    "Created: / 30-08-2013 / 17:05:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

invstatic
    methodsInvoked add: (constantPool at: self fetchBytes2)

    "Created: / 30-08-2013 / 17:05:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

invvirt
    methodsInvoked add: (constantPool at: self fetchBytes2)

    "Created: / 30-08-2013 / 17:05:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

multianewarray
    | classRef |

    classRef := constantPool at: self fetchIndex2.
    self fetchIndex. "/ dimensions
    refdClasses add: classRef.

    "Created: / 09-09-2013 / 12:21:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

new
    | classRef |

    classRef := constantPool at: self fetchIndex2.
    refdClasses add: classRef.

    "Created: / 09-09-2013 / 12:18:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

putfield
    | fieldRef |

    fieldRef := constantPool at: self fetchIndex2.     
    fieldsAccessed add: fieldRef.
    fieldsWritten add: fieldRef.

    "Created: / 30-08-2013 / 13:26:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 30-08-2013 / 17:02:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

putstatic
    | fieldRef |

    fieldRef := constantPool at: self fetchIndex2.     
    staticsWritten add: fieldRef.
    staticsAccessed  add: fieldRef.
    refdClasses add: fieldRef classRef.

    "Created: / 09-09-2013 / 12:16:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer methodsFor:'processing loop'!

process: aMethod receiver: aReceiver arguments: args 
    fieldsAccessed := Set new.
    fieldsRead := Set new.
    fieldsWritten := Set new.

    staticsAccessed := Set new.
    staticsRead  := Set new.
    staticsWritten  := Set new.

    methodsInvoked := Set new.
    refdClasses := Set new.

    "/ Abstract, native or other funny method
    aMethod byteCode isNil ifTrue:[ ^ self ].

    ^ super process: aMethod receiver: aReceiver arguments: args.

    "Created: / 30-08-2013 / 13:23:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-09-2013 / 12:15:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer methodsFor:'queries'!

sends: selector
    ^ self sendsAny: (Array with: selector)

    "Created: / 31-08-2013 / 11:38:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

sends:selector1 or:selector2
    ^ self sendsAny: (Array with: selector1 with: selector2)

    "Modified: / 31-08-2013 / 11:39:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

sendsAny: selectors
    selectors do:[:pair|
        methodsInvoked do:[:methodRef |
            methodRef selector = pair first ifTrue:[
                ^ true
            ]
        ]
    ].
    ^ false

    "Created: / 02-12-2011 / 23:05:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 31-08-2013 / 21:33:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer methodsFor:'queries-statistic'!

messagesPossiblySent
    ^ #()

    "Created: / 30-08-2013 / 14:05:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 31-08-2013 / 10:44:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

messagesSent
    ^ methodsInvoked collect:[:methodRef |methodRef selector ]

    "Created: / 31-08-2013 / 10:44:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 31-08-2013 / 21:32:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

messagesSentToSelf
    ^#()

    "Created: / 31-08-2013 / 09:31:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

messagesSentToSuper
    ^#()

    "Created: / 30-03-2013 / 09:59:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

modifiedClassVars
    ^#() "/ No class vars in Java

    "Created: / 30-08-2013 / 13:16:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

modifiedInstVars
    ^ method isStatic ifTrue:[
        staticsWritten collect:[:ref | ref name ]
    ] ifFalse:[
        fieldsWritten collect:[:ref | ref name ]
    ]

    "Created: / 30-08-2013 / 13:18:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 05-09-2013 / 16:23:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

readGlobals
    | names |

    names := refdClasses collect:[:ref | ref name ].
"/    (names includes: 'sun/misc/Unsafe') ifTrue:[
"/        self halt.
"/    ].
    ^ names

    "Created: / 05-09-2013 / 15:27:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 09-09-2013 / 12:33:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

readInstVars
    ^ method isStatic ifTrue:[
        staticsRead collect:[:ref | ref name ]
    ] ifFalse:[
        fieldsRead collect:[:ref | ref name ]
    ]

    "Created: / 05-09-2013 / 15:27:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

usedClassVars
    ^ #() "/ No class vars in Java

    "Created: / 30-08-2013 / 13:18:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

usedGlobals
    ^ self readGlobals

    "Created: / 05-09-2013 / 15:27:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

usedInstVars
    ^ method isStatic ifTrue:[
        staticsAccessed  collect:[:ref | ref name ]
    ] ifFalse:[
        fieldsAccessed  collect:[:ref | ref name ]
    ]

    "Created: / 30-08-2013 / 13:18:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 05-09-2013 / 16:22:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer methodsFor:'queries-statistic-Java'!

methodsInvoked
    "Return a set of method invoked by the analyzed
     method. 

     Unlike #messagesSent, which return only
     selectors, this method returns a list of method refs,
     so the receivers' declared class is also accessible
     (through ref classRef)"

    ^ methodsInvoked

    "Created: / 31-08-2013 / 23:22:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaMethodAnalyzer class methodsFor:'documentation'!

version_CVS
    ^ '$Header$'
!

version_HG

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