From 717a866d25642626b22b9b3abbd8f98ce95c5e10 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Fri, 17 Aug 2012 19:21:45 +0200 Subject: [PATCH] java runtime: add simple version of instanceof just works if we check for the same type, like: > A a = new A(); > if (a instanceof A) { > [...] --- Mate/Types.hs | 1 + Mate/X86CodeGen.hs | 15 +++++++++++---- Mate/X86TrapHandling.hs | 19 +++++++++++++++++++ tests/InstanceOf1.java | 17 +++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/InstanceOf1.java diff --git a/Mate/Types.hs b/Mate/Types.hs index 1f67aa6..65c8546 100644 --- a/Mate/Types.hs +++ b/Mate/Types.hs @@ -40,6 +40,7 @@ data TrapCause = StaticMethod MethodInfo | -- for static calls VirtualMethod Bool MethodInfo | -- for virtual calls InterfaceMethod Bool MethodInfo | -- for interface calls + InstanceOf B.ByteString | -- class name StaticField StaticFieldInfo deriving Show data StaticFieldInfo = StaticFieldInfo { diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index 710b5b6..448c966 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -173,6 +173,17 @@ emitFromBB cls method = do mov eax (Addr 0x00000000) -- it's a trap push eax return $ Just (trapaddr, StaticField $ buildStaticFieldID cls cpidx) + emit' (INSTANCEOF cpidx) = do + pop eax + mov eax (Disp 0, eax) -- mtable of objectref + trapaddr <- getCurrentOffset + -- place something like `mov edx $mtable_of_objref' instead + emit32 (0x9090ffff :: Word32) >> emit8 (0x90 :: Word8) + cmp eax edx + sete al + movzxb eax al + push eax + return $ Just (trapaddr, InstanceOf $ buildClassID cls cpidx) emit' insn = emit insn >> return Nothing emit :: J.Instruction -> CodeGen e s () @@ -236,10 +247,6 @@ emitFromBB cls method = do mtable <- liftIO $ getMethodTable objname mov (Disp 0, eax) mtable emit (CHECKCAST _) = nop -- TODO(bernhard): ... - -- TODO(bernhard): ... - emit (INSTANCEOF _) = do - pop eax - push (1 :: Word32) emit ATHROW = -- TODO(bernhard): ... emit32 (0xffffffff :: Word32) emit I2C = do diff --git a/Mate/X86TrapHandling.hs b/Mate/X86TrapHandling.hs index f89e2b8..ad7e043 100644 --- a/Mate/X86TrapHandling.hs +++ b/Mate/X86TrapHandling.hs @@ -8,6 +8,7 @@ module Mate.X86TrapHandling ( ) where import qualified Data.Map as M +import qualified Data.ByteString.Lazy as B import Foreign import Foreign.C.Types @@ -24,12 +25,14 @@ data TrapType = | StaticFieldAccess | VirtualMethodCall Bool | InterfaceMethodCall Bool + | InstanceOfMiss B.ByteString getTrapType :: TrapMap -> CPtrdiff -> CPtrdiff -> TrapType getTrapType tmap signal_from from2 = case M.lookup (fromIntegral signal_from) tmap of (Just (StaticMethod _)) -> StaticMethodCall (Just (StaticField _)) -> StaticFieldAccess + (Just (InstanceOf cn)) -> InstanceOfMiss cn (Just _) -> error "getTrapMap: doesn't happen" -- maybe we've a hit on the second `from' value Nothing -> case M.lookup (fromIntegral from2) tmap of @@ -46,6 +49,7 @@ mateHandler eip eax ebx esp = do case getTrapType tmap eip callerAddr of StaticMethodCall -> staticCallHandler eip StaticFieldAccess -> staticFieldHandler eip + (InstanceOfMiss cn) -> instanceOfMissHandler eip cn VirtualMethodCall imm8 -> invokeHandler eax eax esp imm8 InterfaceMethodCall imm8 -> invokeHandler eax ebx esp imm8 @@ -81,6 +85,21 @@ staticFieldHandler eip = do return eip else error "staticFieldHandler: something is wrong here. abort.\n" +instanceOfMissHandler :: CPtrdiff -> B.ByteString -> IO CPtrdiff +instanceOfMissHandler eip classname = do + -- first byte is going to be the opcode + let insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar + -- the next four bytes are the immediate + let imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff + checkMe <- peek imm_ptr + if checkMe == 0x909090ff then -- safety check... + do + mtable <- getMethodTable classname + poke imm_ptr (fromIntegral mtable) + poke insn_ptr 0xba -- `mov edx' opcode + return eip + else error "instanceOfMissHandler: something is wrong here. abort.\n" + invokeHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> Bool -> IO CPtrdiff invokeHandler method_table table2patch esp imm8 = do -- table2patch: note, that can be a method-table or a interface-table diff --git a/tests/InstanceOf1.java b/tests/InstanceOf1.java new file mode 100644 index 0000000..faf3dd9 --- /dev/null +++ b/tests/InstanceOf1.java @@ -0,0 +1,17 @@ +package tests; + +public class InstanceOf1 { + public static void main(String []args) { + Instance1 x = new Instance1(); + if (x instanceof Instance1) { + System.out.printf("x is instance of Instance1 :-)\n"); + } else { + System.out.printf("x is *not* instance of Instance1 :-(\n"); + } + if (x instanceof Instance2) { + System.out.printf("x is instance of Instance2 :-)\n"); + } else { + System.out.printf("x is *not* instance of Instance2 :-(\n"); + } + } +} -- 2.25.1