From: Bernhard Urban Date: Thu, 26 Apr 2012 08:39:10 +0000 (+0200) Subject: strings: put every String from the constantpool in a Map X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mate.git;a=commitdiff_plain;h=b25d636bdeaadc503cab14a9df7c1c8ec7b2c26c strings: put every String from the constantpool in a Map because the spec requires that every constant string has the same address. w0000t @ "Hello World" :-) --- diff --git a/Makefile b/Makefile index 2b4182d..57f77e2 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,8 @@ test: mate $(CLASS_FILES) @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) $< diff --git a/Mate/MethodPool.hs b/Mate/MethodPool.hs index e1eb121..0e146a1 100644 --- a/Mate/MethodPool.hs +++ b/Mate/MethodPool.hs @@ -65,7 +65,8 @@ getMethodEntry signal_from methodtable = do 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 @@ -120,6 +121,7 @@ initMethodPool = do 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 () diff --git a/Mate/Strings.hs b/Mate/Strings.hs new file mode 100644 index 0000000..2867bad --- /dev/null +++ b/Mate/Strings.hs @@ -0,0 +1,41 @@ +{-# 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 diff --git a/Mate/Types.hs b/Mate/Types.hs index 8977143..7f19325 100644 --- a/Mate/Types.hs +++ b/Mate/Types.hs @@ -49,6 +49,10 @@ type ClassMap = M.Map B.ByteString ClassInfo 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 @@ -123,6 +127,12 @@ foreign import ccall "get_virtualmap" 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 @@ -155,3 +165,12 @@ virtualmap2ptr cmap = 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) diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index 2db7a97..15616f5 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -26,6 +26,8 @@ import Mate.BasicBlocks 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) @@ -268,6 +270,12 @@ emitFromBB method cls hmap = do 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 diff --git a/ffi/native.c b/ffi/native.c index 25c159a..a9aa227 100644 --- a/ffi/native.c +++ b/ffi/native.c @@ -19,3 +19,8 @@ void java_io_PrintStream__printf___I_V(int a) { printf("printstream: 0x%08x\n", a); } + +void java_io_PrintStream__println___Ljava_lang_String__V(const char *a) +{ + printf("%s\n", a); +} diff --git a/ffi/trap.c b/ffi/trap.c index 9d70492..7871757 100644 --- a/ffi/trap.c +++ b/ffi/trap.c @@ -39,6 +39,7 @@ NEW_MAP(method) NEW_MAP(trap) NEW_MAP(class) NEW_MAP(virtual) +NEW_MAP(strings) void mainresult(unsigned int a) diff --git a/tests/Native3.java b/tests/Native3.java new file mode 100644 index 0000000..60916e6 --- /dev/null +++ b/tests/Native3.java @@ -0,0 +1,7 @@ +package tests; + +public class Native3 { + public static void main(String []args) { + System.out.println("Hello World"); + } +}