CompiledCode subclass:#JavaMethod
instanceVariableNames:'javaByteCode numArgs numLocals returnType accessFlags name
signature exceptionHandlerTable exceptionTable lineNumberTable
localVariableTable javaClass numStack'
classVariableNames:'SignatureTypeCodes'
poolDictionaries:''
category:'Java-Classes'
!
!JavaMethod class methodsFor:'initialization'!
initialize
SignatureTypeCodes := IdentityDictionary new.
SignatureTypeCodes at:$B put:#byte.
SignatureTypeCodes at:$C put:#char.
SignatureTypeCodes at:$D put:#double.
SignatureTypeCodes at:$F put:#float.
SignatureTypeCodes at:$I put:#int.
SignatureTypeCodes at:$J put:#long.
SignatureTypeCodes at:$S put:#'unsigned short'.
SignatureTypeCodes at:$Z put:#boolean.
SignatureTypeCodes at:$L put:#object.
SignatureTypeCodes at:$[ put:#array.
"
JavaMethod initialize
"
! !
!JavaMethod class methodsFor:'signature parsing'!
argSigArrayFromSignature:aSignature
"given a signature, return a specArray for the arguments"
|s argSpec retvalSpec|
s := aSignature readStream.
s next ~~ $( ifTrue:[self halt. ^ name].
^ self argSigArrayFromStream:s.
"
JavaMethod argSigArrayFromSignature:'(LObject;)V'
JavaMethod argSigArrayFromSignature:'(BB)S'
JavaMethod argSigArrayFromSignature:'(LObject;LObject;II)V'
"
!
argSigArrayFromStream:s
"parse an argSpec, return an array of specs - see java doc"
|argSpec spec|
spec := #().
[s atEnd or:[s peek == $)]] whileFalse:[
"/ s peek == Character space ifTrue:[
"/ s next
"/ ] ifFalse:[
argSpec := self fieldTypeFromStream:s.
spec := spec copyWith:argSpec.
"/ ]
].
^ spec
!
argSpecFromSignature:aSignature withName:name
"given a signature, return a spec"
|s argSpec retvalSpec|
s := aSignature readStream.
s next ~~ $( ifTrue:[self halt. ^ name].
argSpec := self argSpecFromStream:s.
s next ~~ $) ifTrue:[self halt. ^ name].
^ name , ' (' , argSpec , ')'
"
JavaMethod argSpecFromSignature:'(LObject;)V' withName:'foo'
JavaMethod argSpecFromSignature:'(BB)S' withName:'foo'
"
!
argSpecFromStream:s
"parse an argSpec - see java doc"
|argSpec spec|
spec := ''.
[s atEnd or:[s peek == $)]] whileFalse:[
"/ s peek == Character space ifTrue:[
"/ s next
"/ ] ifFalse:[
argSpec := self fieldTypeFromStream:s.
spec size ~~ 0 ifTrue:[
spec := spec , ' '
].
spec := spec , argSpec.
"/ ]
].
^ spec
!
fieldTypeFromStream:s
"parse a fieldTypeSpec - see java doc"
|typeChar typeSym spec elType size className|
typeChar := s next.
typeSym := SignatureTypeCodes at:typeChar ifAbsent:#unknown.
typeSym == #unknown ifTrue:[
^ typeSym
].
typeSym == #object ifTrue:[
className := s upTo:$;.
"/ strip off default
"/ (className startsWith:'java/lang/') ifTrue:[
"/ ^ className copyFrom:11
"/ ].
^ className copy replaceAll:$/ by:$.
].
typeSym == #array ifTrue:[
s peek isDigit ifTrue:[
size := Integer readFrom:s.
elType := self fieldTypeFromStream:s.
^ elType , '[' , size printString , ']'
].
elType := self fieldTypeFromStream:s.
^ elType , '[]'
].
^ typeSym
!
numArgsFromSignature:aSignature
"given a signature, return the number of args"
|s argSpec|
s := aSignature readStream.
s next ~~ $( ifTrue:[self halt. ^ name].
^ self numArgsFromStream:s.
"
JavaMethod numArgsFromSignature:'(LObject;)V'
JavaMethod numArgsFromSignature:'(BB)S'
JavaMethod numArgsFromSignature:'()V'
"
!
numArgsFromStream:s
"parse an argSpec - see java doc"
|argSpec n t|
n := 0.
[s atEnd or:[s peek == $)]] whileFalse:[
t := self fieldTypeFromStream:s.
"/
"/ some args count as 2
"/
t == #long ifTrue:[
n := n + 2.
] ifFalse:[
t == #double ifTrue:[
n := n + 2
] ifFalse:[
n := n + 1.
]
]
].
^ n
!
retValSpecFromSignature:aSignature
"given a signature, return a spec"
|s argSpec retvalSpec|
s := aSignature readStream.
s next ~~ $( ifTrue:[self halt. ^ name].
argSpec := self argSpecFromStream:s.
s next ~~ $) ifTrue:[self halt. ^ name].
retvalSpec := self retvalSpecFromStream:s.
^ retvalSpec
"
JavaMethod retValSpecFromSignature:'(LObject;)V'
JavaMethod retValSpecFromSignature:'(BB)S'
"
!
returnTypeFromSignature:aSignature
"given a signature, return its type as a string"
|s c argSpec retvalSpec|
s := aSignature readStream.
(c := s peek) ~~ $( ifTrue:[
c == $' ifTrue:[
[s peek ~= $'] whileTrue:[s next].
s next.
^ (self retvalSpecFromStream:s)
].
^ (self retvalSpecFromStream:s)
].
s next.
self argSpecFromStream:s.
s next ~~ $) ifTrue:[self halt. ^ nil].
^ (self retvalSpecFromStream:s)
"
JavaMethod returnTypeFromSignature:'(LObject;)V'
JavaMethod returnTypeFromSignature:'(BB)S'
JavaMethod returnTypeFromSignature:'()J'
JavaMethod returnTypeFromSignature:'''first''J'
"
!
returnsVoidFromSignature:aSignature
"given a signature, return true if it returns void, false if not"
^ (self typeFromSignature:aSignature) = 'void'
"
JavaMethod returnsVoidFromSignature:'(LObject;)V'
JavaMethod returnsVoidFromSignature:'(BB)S'
"
!
retvalSpecFromStream:s
"parse a retvalSpec - see java doc"
|argSpec spec|
s atEnd ifTrue:[self halt. ^ #void].
s peek == $V ifTrue:[^ #void].
^ self fieldTypeFromStream:s
!
specFromSignature:aSignature withName:name
"given a signature, return a spec"
|s argSpec retvalSpec|
s := aSignature readStream.
s next ~~ $( ifTrue:[self halt. ^ name].
argSpec := self argSpecFromStream:s.
s next ~~ $) ifTrue:[self halt. ^ name].
retvalSpec := self retvalSpecFromStream:s.
^ retvalSpec , ' ' , name , ' (' , argSpec , ')'
"
JavaMethod specFromSignature:'(LObject;)V' withName:'foo'
JavaMethod specFromSignature:'(BB)S' withName:'foo'
"
!
typeFromSignature:aSignature
"given a signature, return its type as a string"
|s c argSpec retvalSpec|
s := aSignature readStream.
(c := s peek) ~~ $( ifTrue:[
c == $' ifTrue:[
s next.
[s peek ~= $'] whileTrue:[s next].
s next.
^ (self retvalSpecFromStream:s)
].
^ (self retvalSpecFromStream:s)
].
s next.
self argSpecFromStream:s.
s next ~~ $) ifTrue:[self halt. ^ nil].
^ (self retvalSpecFromStream:s)
"
JavaMethod typeFromSignature:'(LObject;)V'
JavaMethod typeFromSignature:'(BB)S'
JavaMethod typeFromSignature:'()J'
JavaMethod typeFromSignature:'J'
JavaMethod typeFromSignature:'''first''J'
"
! !
!JavaMethod methodsFor:'accessing'!
argSignature
^ self class argSigArrayFromSignature:signature
!
constantPool
^ javaClass constantPool
"Modified: 16.4.1996 / 12:36:27 / cg"
"Created: 16.4.1996 / 15:28:50 / cg"
!
containingClass
^ javaClass
!
decompiledSource
|s|
s := '' writeStream.
self decompileTo:s.
^ s contents
!
exceptionHandlerTable
^ exceptionHandlerTable
"Modified: 16.4.1996 / 12:49:06 / cg"
"Created: 7.2.1997 / 20:04:20 / cg"
!
exceptionTable
^ exceptionTable
"Created: 16.4.1996 / 12:34:04 / cg"
"Modified: 16.4.1996 / 12:49:06 / cg"
!
hasLineNumberInformation
^ lineNumberTable notNil
"Created: 16.4.1996 / 12:34:04 / cg"
"Modified: 16.4.1996 / 12:49:06 / cg"
!
javaByteCode
^ javaByteCode
"Modified: 16.4.1996 / 12:36:27 / cg"
"Created: 16.4.1996 / 14:55:44 / cg"
!
javaClass
^ javaClass
"Modified: 16.4.1996 / 12:36:27 / cg"
"Created: 16.4.1996 / 14:55:44 / cg"
!
lineNumber
^ lineNumberTable at:2
"Created: 16.4.1996 / 12:34:04 / cg"
"Modified: 16.4.1996 / 12:49:06 / cg"
!
lineNumberTable
^ lineNumberTable
"Created: 16.4.1996 / 12:34:04 / cg"
"Modified: 16.4.1996 / 12:49:06 / cg"
!
localVariableTable
^ localVariableTable
"
JavaMethod allInstancesDo:[:m| m localVariableTable notNil ifTrue:[self halt]]
"
!
methodArgAndVarNames
^ ((1 to:self numArgs) collect:[:i | 'arg' , i printString])
,
((1 to:self numVars) collect:[:i | 'local' , i printString])
!
methodArgNames
localVariableTable notNil ifTrue:[
^ (1 to:self numArgs) collect:
[:argIndex | |slot name|
"/ search for an entry with that index (slot),
"/ which has is valid at PC 0
self isStatic ifTrue:[
slot := argIndex
] ifFalse:[
slot := argIndex + 1
].
name := localVariableTable nameForSlot:slot atPC:0.
name isNil ifTrue:[
'arg' , argIndex printString
] ifFalse:[
name
].
]
].
^ (1 to:self numArgs) collect:[:i | 'arg' , i printString]
!
name
^ name
"Created: 16.4.1996 / 11:34:22 / cg"
!
numArgs
numArgs isNil ifTrue:[^ 0].
^ numArgs
!
numLocals
numLocals isNil ifTrue:[^ 0].
^ numLocals
!
numStack
numStack isNil ifTrue:[^ 0].
^ numStack
!
numVars
numLocals isNil ifTrue:[^ 0].
numArgs isNil ifTrue:[^ numLocals].
^ numLocals - numArgs
!
numberOfMethodArgs:n
numArgs := n
!
retValSignature
^ self class retValSpecFromSignature:signature
!
returnType
^ returnType
!
returnsDouble
^ returnType == #double
!
returnsLong
^ returnType == #long
!
returnsVoid
^ returnType == #void
!
setAccessFlags:flags
accessFlags := flags.
"Created: 16.4.1996 / 11:34:14 / cg"
!
setCode:codeBytes maxStack:max_stack maxLocals:max_locals u1:unknown1 u2:unknown2
javaByteCode := codeBytes.
numStack := max_stack.
numLocals := max_locals.
"/ self displayString printNL.
"/ ' nStack: ' print. numStack print.
"/ ' nLocal: ' print. numLocals print.
"/ ' u1: ' print. unknown1 print.
"/ ' u2: ' print. unknown2 printNL.
!
setExceptionHandlerTable:anArray
exceptionHandlerTable := anArray.
"Created: 16.4.1996 / 12:34:04 / cg"
!
setExceptionTable:anArray
exceptionTable := anArray.
"Created: 16.4.1996 / 12:34:04 / cg"
!
setJavaClass:aJavaClass
javaClass := aJavaClass
"Modified: 16.4.1996 / 12:36:27 / cg"
"Created: 16.4.1996 / 15:28:15 / cg"
!
setLineNumberTable:anArrayOfPCtoLineAssociations
"since this uses up lots of memory, compress it"
|allBytes allWords idx|
allBytes := allWords := true.
anArrayOfPCtoLineAssociations do:[:assoc |
assoc key > 255 ifTrue:[
allBytes := false.
assoc key > 16rFFFF ifTrue:[
allWords := false.
].
].
assoc value > 255 ifTrue:[
allBytes := false.
assoc value > 16rFFFF ifTrue:[
allWords := false
].
].
].
allBytes ifTrue:[
lineNumberTable := ByteArray new:(anArrayOfPCtoLineAssociations size * 2).
] ifFalse:[
allWords ifTrue:[
lineNumberTable := WordArray new:(anArrayOfPCtoLineAssociations size * 2).
] ifFalse:[
lineNumberTable := Array new:(anArrayOfPCtoLineAssociations size * 2).
]
].
idx := 1.
anArrayOfPCtoLineAssociations do:[:assoc |
lineNumberTable at:idx put:assoc key.
lineNumberTable at:idx+1 put:assoc value.
idx := idx + 2.
].
"Created: 16.4.1996 / 12:34:04 / cg"
"Modified: 16.4.1996 / 12:49:06 / cg"
!
setLocalVariableTable:anArray
localVariableTable := anArray.
!
setName:aString
name := aString asSymbol.
"Created: 16.4.1996 / 11:34:22 / cg"
!
setSignature:aString
signature := aString asSymbol.
self numberOfMethodArgs:(self class numArgsFromSignature:aString).
returnType := self class typeFromSignature:aString.
"Created: 16.4.1996 / 11:34:29 / cg"
!
signature
^ signature
"Created: 16.4.1996 / 11:34:29 / cg"
!
source
|classSource|
lineNumberTable notNil ifTrue:[
classSource := javaClass source.
classSource notNil ifTrue:[^ classSource].
].
^ self decompiledSource
!
sourceFilename
^ javaClass sourceFile
! !
!JavaMethod methodsFor:'decompiling'!
decompileTo:aStream
JavaDecompiler decompile:self to:aStream.
^ true
! !
!JavaMethod methodsFor:'methodref interchangability'!
method
^ self
! !
!JavaMethod methodsFor:'printing & storing'!
displayString
^ 'JavaMethod(' , javaClass name , '::' , self signatureName , ')'
!
printStringForBrowserWithSelector:selector
"/ self isStatic ifTrue:[
"/ ^ 'static ' , self signatureName
"/ ].
self isBreakpointed ifTrue:[
^ '!! ' , self signatureName
].
^ self signatureName
!
shortDisplayString
^ javaClass name , '::' , self signatureNameWithoutReturnType
!
signatureName
"return a string to be used when browsing"
^ self class specFromSignature:signature withName:name
!
signatureNameWithoutReturnType
"return a string to be used when browsing"
^ self class argSpecFromSignature:signature withName:name
! !
!JavaMethod methodsFor:'queries'!
handlerFor:anException at:pc
exceptionHandlerTable isNil ifTrue:[^ nil].
exceptionHandlerTable do:[:entry |
|hpc|
hpc := entry handlerPCFor:anException at:pc in:self.
hpc notNil ifTrue:[^ hpc].
].
^ nil
!
hasResource
^ false
!
isAbstract
^ (accessFlags bitAnd:16r0400) ~~ 0
!
isBreakpointed
^ false
!
isFinal
^ (accessFlags bitAnd:16r0010) ~~ 0
!
isNative
^ (accessFlags bitAnd:16r0100) ~~ 0
!
isPrivate
^ (accessFlags bitAnd:16r0002) ~~ 0
!
isProtected
^ (accessFlags bitAnd:16r0004) ~~ 0
!
isPublic
^ (accessFlags bitAnd:16r0001) ~~ 0
!
isStatic
^ (accessFlags bitAnd:16r0008) ~~ 0
!
isSynchronized
^ (accessFlags bitAnd:16r0020) ~~ 0
!
isUnloaded
^ false
!
lineNumberForPC:pc
|last num text classSource|
num := nil.
lineNumberTable notNil ifTrue:[
classSource := javaClass source.
classSource notNil ifTrue:[
lineNumberTable pairWiseDo:[:lPc :lNr |
lPc >= pc ifTrue:[
lPc == pc ifTrue:[^ lNr].
last isNil ifTrue:[^ lNr].
^ last.
].
last := lNr.
].
last notNil ifTrue:[
^ last
].
^ lineNumberTable at:2
].
].
"/ decompile and look which line the pc falls into
text := self decompiledSource asCollectionOfLines.
text keysAndValuesDo:[:lineNr :line |
|nr|
(line startsWith:' ') ifFalse:[
nr := Integer readFrom:line onError:0.
nr >= pc ifTrue:[
^ lineNr
]
]
].
^ num
"Modified: 17.3.1997 / 18:06:43 / cg"
!
who
"return the class and selector of where I am defined in."
|sel|
sel := javaClass methodDictionary keyAtValue:self ifAbsent:nil.
sel isNil ifTrue:[^ nil].
^ Method::MethodWhoInfo class:javaClass selector:sel.
! !
!JavaMethod class methodsFor:'documentation'!
version
^ '$Header: /home/jv/Projects/SmalltalkX/repositories/cvs/stx/libjava/JavaMethod.st,v 1.31 1997/03/17 17:16:07 cg Exp $'
! !
JavaMethod initialize!