Skip to content

Commit

Permalink
Allow invokespecial and invokestatic to refer to interface methods.
Browse files Browse the repository at this point in the history
Previously the parser would only work if `invokespecial` or
`invokestatic` referred to an ordinary method, and would fail if it
found a reference to an interface method. But according to section
6.5 of the JVM spec, "the run-time constant pool item ... must be a
symbolic reference to a method or an interface method." This patch
updates the parser to comply with the spec.
  • Loading branch information
Brian Huffman committed Nov 19, 2020
1 parent 5368a84 commit 8ff37de
Showing 1 changed file with 19 additions and 8 deletions.
27 changes: 19 additions & 8 deletions src/Language/JVM/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -372,20 +372,31 @@ poolInterfaceMethodRef :: ConstantPool -> ConstantPoolIndex -> (Type, MethodKey)
poolInterfaceMethodRef cp i
= case cp ! i of
InterfaceMethodRef classIndex ntIndex ->
let (name, fieldDescriptor) = poolNameAndType cp ntIndex
interfaceType = poolClassType cp classIndex
in (interfaceType, makeMethodKey name fieldDescriptor)
poolTypeAndMethodKey cp classIndex ntIndex
_ -> error ("Index " ++ show i ++ " is not an interface method reference.")

poolMethodRef :: ConstantPool -> ConstantPoolIndex -> (Type, MethodKey)
poolMethodRef cp i
= case cp ! i of
MethodRef classIndex ntIndex ->
let (name, fieldDescriptor) = poolNameAndType cp ntIndex
classType = poolClassType cp classIndex
in (classType, makeMethodKey name fieldDescriptor)
poolTypeAndMethodKey cp classIndex ntIndex
_ -> error ("Index " ++ show i ++ " is not a method reference.")

poolMethodOrInterfaceRef :: ConstantPool -> ConstantPoolIndex -> (Type, MethodKey)
poolMethodOrInterfaceRef cp i
= case cp ! i of
MethodRef classIndex ntIndex ->
poolTypeAndMethodKey cp classIndex ntIndex
InterfaceMethodRef classIndex ntIndex ->
poolTypeAndMethodKey cp classIndex ntIndex
_ -> error ("Index " ++ show i ++ " is not a method or interface method reference.")

poolTypeAndMethodKey :: ConstantPool -> ConstantPoolIndex -> ConstantPoolIndex -> (Type, MethodKey)
poolTypeAndMethodKey cp classIndex ntIndex =
let (name, fieldDescriptor) = poolNameAndType cp ntIndex
classType = poolClassType cp classIndex
in (classType, makeMethodKey name fieldDescriptor)

_uncurry3 :: (a -> b -> c -> d) -> (a,b,c) -> d
_uncurry3 fn (a,b,c) = fn a b c

Expand Down Expand Up @@ -602,10 +613,10 @@ getInstruction cp address = do
let (classType, key) = poolMethodRef cp index
return $ Invokevirtual classType key
0xB7 -> do index <- getWord16be
let (classType, key) = poolMethodRef cp index
let (classType, key) = poolMethodOrInterfaceRef cp index
return $ Invokespecial classType key
0xB8 -> do index <- getWord16be
let (ClassType cName, key) = poolMethodRef cp index
let (ClassType cName, key) = poolMethodOrInterfaceRef cp index
in return $ Invokestatic cName key
0xB9 -> do index <- getWord16be
_ <- getWord8
Expand Down

0 comments on commit 8ff37de

Please sign in to comment.