@printf "should be: 0x%08x 0x%08x\n" 0x1337 0x1337
./$< tests/Native2 | grep "printstream"
@printf "should be: 0x%08x\n" 0x1337
+ ./$< tests/Native2 | grep "Hello World"
+ @printf "should be: %s" "Hello World"
%.class: %.java
$(JAVAC) $<
return $ fromIntegral entry
Nothing -> error $ (show method) ++ " not found. abort"
True -> do
- let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace "(" "_" (replace ")" "_" $ toString $ encode sig))
+ -- TODO(bernhard): cleaner please... *do'h*
+ let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace ";" "_" $ replace "/" "_" $ replace "(" "_" (replace ")" "_" $ toString $ encode sig))
printf "native-call: symbol: %s\n" symbol
nf <- loadNativeFunction symbol
let w32_nf = fromIntegral nf
tmap2ptr M.empty >>= set_trapmap
classmap2ptr M.empty >>= set_classmap
virtualmap2ptr M.empty >>= set_virtualmap
+ stringsmap2ptr M.empty >>= set_stringsmap
addMethodRef :: Word32 -> MethodInfo -> [B.ByteString] -> IO ()
--- /dev/null
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Mate.Strings (
+ getUniqueStringAddr
+ ) where
+
+import Data.Word
+import qualified Data.Map as M
+import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString.Internal as BI
+import Text.Printf
+
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Marshal.Array
+
+import Mate.Types
+
+
+getUniqueStringAddr :: B.ByteString -> IO Word32
+getUniqueStringAddr str = do
+ smap <- get_stringsmap >>= ptr2stringsmap
+ case M.lookup str smap of
+ Nothing -> do
+ addr <- allocateJavaString str
+ let smap' = M.insert str addr smap
+ stringsmap2ptr smap' >>= set_stringsmap
+ return addr
+ Just addr -> return addr
+
+-- TOOD(bernhard): quite hackish
+allocateJavaString :: B.ByteString -> IO Word32
+allocateJavaString str = do
+ let strlen = fromIntegral $ B.length str
+ let str_unpacked = (map fromIntegral $ B.unpack str) :: [Word8]
+ arr <- newArray str_unpacked
+ newstr <- BI.create strlen (\x -> BI.memcpy x arr (fromIntegral strlen))
+ let (newstrptr, _, _) = BI.toForeignPtr newstr
+ let w32_ptr = fromIntegral $ ptrToIntPtr $ unsafeForeignPtrToPtr newstrptr
+ printf "new str ptr: 0x%08x\n" w32_ptr
+ return w32_ptr
type FieldMap = M.Map B.ByteString Int32
+-- java strings are allocated once, therefore we
+-- use a hashmap to store the address for a String
+type StringsMap = M.Map B.ByteString Word32
+
-- map "methodtable addr" to "classname"
-- we need that to identify the actual type
-- on the invokevirtual insn
foreign import ccall "set_virtualmap"
set_virtualmap :: Ptr () -> IO ()
+foreign import ccall "get_stringsmap"
+ get_stringsmap :: IO (Ptr ())
+
+foreign import ccall "set_stringsmap"
+ set_stringsmap :: Ptr () -> IO ()
+
-- TODO(bernhard): make some typeclass magic 'n stuff
mmap2ptr :: MMap -> IO (Ptr ())
mmap2ptr mmap = do
ptr2virtualmap :: Ptr () -> IO VirtualMap
ptr2virtualmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr cmap)
+
+
+stringsmap2ptr :: StringsMap -> IO (Ptr ())
+stringsmap2ptr cmap = do
+ ptr_cmap <- newStablePtr cmap
+ return $ castStablePtrToPtr ptr_cmap
+
+ptr2stringsmap :: Ptr () -> IO StringsMap
+ptr2stringsmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr cmap)
import Mate.Types
import Mate.Utilities
import Mate.ClassPool
+import Mate.Strings
+
foreign import ccall "dynamic"
code_int :: FunPtr (CInt -> CInt -> IO CInt) -> (CInt -> CInt -> IO CInt)
pop eax
mov (Disp (cArgs x), ebp) eax
+ emit (LDC1 x) = emit (LDC2 $ fromIntegral x)
+ emit (LDC2 x) = do
+ let value = case (constsPool cls) M.! x of
+ (CString s) -> unsafePerformIO $ getUniqueStringAddr s
+ _ -> error $ "LDCI... missing impl."
+ push value
emit (GETFIELD x) = do
pop eax -- this pointer
let (cname, fname) = buildFieldOffset cls x
{
printf("printstream: 0x%08x\n", a);
}
+
+void java_io_PrintStream__println___Ljava_lang_String__V(const char *a)
+{
+ printf("%s\n", a);
+}
NEW_MAP(trap)
NEW_MAP(class)
NEW_MAP(virtual)
+NEW_MAP(strings)
void mainresult(unsigned int a)
--- /dev/null
+package tests;
+
+public class Native3 {
+ public static void main(String []args) {
+ System.out.println("Hello World");
+ }
+}