From: Bernhard Urban Date: Fri, 17 Aug 2012 17:21:45 +0000 (+0200) Subject: new insn: fix wrong behaviour on lazy class init X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mate.git;a=commitdiff_plain;h=094e3cea9aa9d638b071fb52a12f04f6ddd80dc1 new insn: fix wrong behaviour on lazy class init TODO: - invokevirtual - invokeinterface --- diff --git a/Mate/ClassPool.hs b/Mate/ClassPool.hs index e6c5bfe..8874999 100644 --- a/Mate/ClassPool.hs +++ b/Mate/ClassPool.hs @@ -3,6 +3,7 @@ #include "debug.h" module Mate.ClassPool ( getClassInfo, + classLoaded, getClassFile, getMethodTable, getObjectSize, @@ -58,6 +59,11 @@ getClassInfo path = do Nothing -> loadAndInitClass path Just ci -> return ci +classLoaded :: B.ByteString -> IO Bool +classLoaded path = do + class_map <- getClassMap + return $ M.member path class_map + getClassFile :: B.ByteString -> IO (Class Direct) getClassFile path = do ci <- getClassInfo path diff --git a/Mate/Types.hs b/Mate/Types.hs index 65c8546..831744a 100644 --- a/Mate/Types.hs +++ b/Mate/Types.hs @@ -41,6 +41,7 @@ data TrapCause = VirtualMethod Bool MethodInfo | -- for virtual calls InterfaceMethod Bool MethodInfo | -- for interface calls InstanceOf B.ByteString | -- class name + NewObject B.ByteString | -- class name StaticField StaticFieldInfo deriving Show data StaticFieldInfo = StaticFieldInfo { diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index f1f9969..ffdc83d 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -192,6 +192,16 @@ emitFromBB cls method = do push eax forceRegDump return $ Just (trapaddr, InstanceOf $ buildClassID cls cpidx) + emit' (NEW objidx) = do + let objname = buildClassID cls objidx + trapaddr <- getCurrentOffset + -- place something like `push $objsize' instead + emit32 (0x9090ffff :: Word32) >> emit8 (0x90 :: Word8) + callMalloc + -- 0x13371337 is just a placeholder; will be replaced with mtable ptr + mov (Disp 0, eax) (0x13371337 :: Word32) + return $ Just (trapaddr, NewObject objname) + emit' insn = emit insn >> return Nothing emit :: J.Instruction -> CodeGen e s () @@ -245,15 +255,7 @@ emitFromBB cls method = do pop ebx -- length mov (Disp 0, eax) ebx -- store length at offset 0 push eax -- push ref again - emit (NEW objidx) = do - let objname = buildClassID cls objidx - amount <- liftIO $ getObjectSize objname - push (amount :: Word32) - callMalloc - -- TODO(bernhard): save reference somewhere for GC - -- set method table pointer - mtable <- liftIO $ getMethodTable objname - mov (Disp 0, eax) mtable + emit (CHECKCAST _) = nop -- TODO(bernhard): ... emit ATHROW = -- TODO(bernhard): ... emit32 (0xffffffff :: Word32) diff --git a/Mate/X86TrapHandling.hs b/Mate/X86TrapHandling.hs index 325f792..493a3ce 100644 --- a/Mate/X86TrapHandling.hs +++ b/Mate/X86TrapHandling.hs @@ -26,6 +26,7 @@ data TrapType = | VirtualMethodCall Bool | InterfaceMethodCall Bool | InstanceOfMiss B.ByteString + | NewObjectTrap B.ByteString | NoKnownTrap String getTrapType :: TrapMap -> CPtrdiff -> CPtrdiff -> TrapType @@ -34,6 +35,7 @@ getTrapType tmap signal_from from2 = (Just (StaticMethod _)) -> StaticMethodCall (Just (StaticField _)) -> StaticFieldAccess (Just (InstanceOf cn)) -> InstanceOfMiss cn + (Just (NewObject cn)) -> NewObjectTrap cn (Just _) -> NoKnownTrap "getTrapMap: doesn't happen" -- maybe we've a hit on the second `from' value Nothing -> case M.lookup (fromIntegral from2) tmap of @@ -51,6 +53,7 @@ mateHandler eip eax ebx esp esi = do StaticMethodCall -> staticCallHandler eip StaticFieldAccess -> staticFieldHandler eip (InstanceOfMiss cn) -> instanceOfMissHandler eip cn + (NewObjectTrap cn) -> newObjectHandler eip cn VirtualMethodCall imm8 -> invokeHandler eax eax esp imm8 InterfaceMethodCall imm8 -> invokeHandler eax ebx esp imm8 NoKnownTrap err -> @@ -105,6 +108,22 @@ instanceOfMissHandler eip classname = do return eip else error "instanceOfMissHandler: something is wrong here. abort.\n" +newObjectHandler :: CPtrdiff -> B.ByteString -> IO CPtrdiff +newObjectHandler eip classname = do + let push_insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar + let push_imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff + let mov_imm_ptr = intPtrToPtr (fromIntegral (eip + 16)) :: Ptr CPtrdiff + checkMe <- peek mov_imm_ptr + if checkMe == 0x13371337 + then do + objsize <- getObjectSize classname + mtable <- getMethodTable classname + poke push_insn_ptr 0x68 -- push_imm insn + poke push_imm_ptr (fromIntegral objsize) + poke mov_imm_ptr (fromIntegral mtable) + return eip + else error "newObjectHandler: 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/Instance5.java b/tests/Instance5.java new file mode 100644 index 0000000..d3f3fb8 --- /dev/null +++ b/tests/Instance5.java @@ -0,0 +1,19 @@ +package tests; + +public class Instance5 { + public static void main(String []args) { + int i_am_null = 0; + if (i_am_null > 0) { + new Instance5_notload(); + System.out.printf("loaded notload stuff o_O\n"); + } else { + System.out.printf("Nothing to do here\n"); + } + } +} + +class Instance5_notload { + static { + System.out.printf("sup, I'm Instance5_notload\n"); + } +}