module Mate.ClassHierarchy
( isInstanceOf
+ , addClassEntry
) where
+import qualified Data.Map as M
import qualified Data.ByteString.Lazy as B
import Control.Applicative
+import Control.Monad
import Text.Printf
+import Foreign
+import Data.IORef
+
import Mate.NativeSizes
import Mate.ClassPool
data Class
= Class
{ clMtable :: NativeWord
- , clSuperClass :: Class
+ , clSuperClass :: NativeWord
, clInterfaces :: [Interface]
}
| JavaLangObject
{ ifSuperInterfaces :: [Interface]
}
+type HierMap = (M.Map NativeWord Class)
+classHier :: IORef HierMap
+{-# NOINLINE classHier #-}
+classHier = unsafePerformIO $ newIORef M.empty
+
+readHier :: IO HierMap
+readHier = readIORef classHier
+
+writeHier :: HierMap -> IO ()
+writeHier = writeIORef classHier
+
+
isInstanceOf :: NativeWord -> B.ByteString -> IO Bool
-isInstanceOf obj_mtable classname = do
- (== obj_mtable) <$> getMethodTable classname
+isInstanceOf 0 _ = return False
+isInstanceOf obj classname = do
+ obj_mtable <- peek (intPtrToPtr . fromIntegral $ obj)
+ class_mtable <- getMethodTable classname
+ ch <- readHier
+ return $ checkInstance obj_mtable class_mtable ch
+
+checkInstance :: NativeWord -> NativeWord -> HierMap -> Bool
+checkInstance obj cl_mtable ch
+ | obj == cl_mtable = True
+ | otherwise =
+ case ch M.! obj of
+ Class _ super _ -> checkInstance super cl_mtable ch
+ JavaLangObject _ -> False
+
+addClassEntry :: NativeWord -> NativeWord -> IO ()
+addClassEntry mtable 0 = do
+ ch <- readHier
+ writeHier (M.insert mtable (JavaLangObject mtable) ch)
+addClassEntry mtable super_mtable = do
+ ch <- readHier
+ when (not $ M.member super_mtable ch) $ error "classhierarchy: superclass should be in hierarchy!"
+ let cl = Class mtable super_mtable []
+ writeHier (M.insert mtable cl ch)
--- /dev/null
+module Mate.ClassHierarchy
+ ( isInstanceOf
+ , addClassEntry
+ ) where
+
+import qualified Data.ByteString.Lazy as B
+import Mate.NativeSizes
+
+isInstanceOf :: NativeWord -> B.ByteString -> IO Bool
+addClassEntry :: NativeWord -> NativeWord -> IO ()
import Mate.Debug
import Mate.GarbageAlloc
import Mate.NativeSizes
+import {-# SOURCE #-} Mate.ClassHierarchy
getClassInfo :: B.ByteString -> IO ClassInfo
getClassInfo path = do
class_map <- getClassMap
let new_ci = ClassInfo path cfile staticmap fieldmap methodmap mbase False
setClassMap $ M.insert path new_ci class_map
+
+ -- add Class to Hierarchy
+ super_mtable <- case superclass of
+ Nothing -> return 0
+ Just x -> getMethodTable $ ciName x
+ addClassEntry mbase super_mtable
+
return new_ci
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); nop
+ emit32 (0x9090ffff :: Word32)
push (0 :: Word32)
let patcher reax reip = do
- -- mtable <- liftIO $ getMethodTable (buildClassID cls cpidx)
- -- mov edx mtable
- emit32 (0x9090ffff :: Word32); nop
+ emit32 (0x9090ffff :: Word32)
let classname = buildClassID cls cpidx
check <- liftIO $ isInstanceOf (fromIntegral reax) classname
if check
then push (1 :: Word32)
else push (0 :: Word32)
- return (reip + 5)
- -- cmp eax edx
- -- sete al
- -- movzxb eax al
- -- push eax
- -- forceRegDump
+ return (reip + 4)
return $ Just (trapaddr, InstanceOf patcher)
emit' (NEW objidx) = do
let objname = buildClassID cls objidx
--- /dev/null
+package tests;
+
+public class InstanceOf2 {
+ public static void main(String []args) {
+ System.out.printf("x = new InstanceOf2_local;\n");
+ Instance1 x = new InstanceOf2_local();
+ checkInstance(null instanceof Instance1, "null", "Instance1");
+ checkInstance(x instanceof Instance1, "x", "Instance1");
+ checkInstance(x instanceof Instance2, "x", "Instance2");
+ checkInstance(x instanceof InstanceOf2_local, "x", "InstanceOf2_local");
+ checkInstance(x instanceof Object, "x", "Object");
+ checkInstance(x instanceof InstanceOf2_local2, "x", "InstanceOf2_local2");
+
+ System.out.printf("\n\n");
+ System.out.printf("y = new InstanceOf2_local2;\n");
+ Object y = new InstanceOf2_local2();
+ checkInstance(null instanceof Instance1, "null", "Instance1");
+ checkInstance(y instanceof Instance1, "y", "Instance1");
+ checkInstance(y instanceof Instance2, "y", "Instance2");
+ checkInstance(y instanceof InstanceOf2_local, "y", "InstanceOf2_local");
+ checkInstance(y instanceof Object, "y", "Object");
+ checkInstance(y instanceof InstanceOf2_local2, "y", "InstanceOf2_local2");
+ }
+
+ public static void checkInstance(boolean cond, String obj, String classname) {
+ System.out.printf(obj);
+ if (cond) {
+ System.out.printf(" is instance of ");
+ System.out.printf(classname);
+ System.out.printf(" :-)\n");
+ } else {
+ System.out.printf(" is *not* instance of ");
+ System.out.printf(classname);
+ System.out.printf(" :-(\n");
+ }
+ }
+}
+
+
+class InstanceOf2_local extends Instance1 {
+}
+
+class InstanceOf2_local2 extends InstanceOf2_local {
+}