allocate memories and tables

This commit is contained in:
Ilya Rezvov
2018-03-11 19:11:19 -07:00
parent 867092c820
commit 93d6d4a417
2 changed files with 39 additions and 21 deletions
+39 -15
View File
@@ -9,7 +9,7 @@ import qualified Data.Map as Map
import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy as TL
import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy as LBS
import Data.Vector (Vector, (!)) import Data.Vector (Vector, (!), (!?))
import qualified Data.Vector as Vector import qualified Data.Vector as Vector
import Data.IORef (IORef, newIORef, readIORef) import Data.IORef (IORef, newIORef, readIORef)
import Data.Array.IO (IOArray, newArray, readArray, writeArray) import Data.Array.IO (IOArray, newArray, readArray, writeArray)
@@ -41,12 +41,12 @@ type Address = Int
data TableInstance = TableInstance { data TableInstance = TableInstance {
elements :: Vector (Maybe Address), elements :: Vector (Maybe Address),
maxLen :: Int maxLen :: Maybe Int
} }
data MemoryInstance = MemoryInstance { data MemoryInstance = MemoryInstance {
memory :: IOArray Int Word32, memory :: IOArray Int Word32,
maxLen :: Int -- in page size (64Ki) maxLen :: Maybe Int -- in page size (64Ki)
} }
data GlobalInstance = GIConst Value | GIMut (IORef Value) data GlobalInstance = GIConst Value | GIMut (IORef Value)
@@ -143,41 +143,65 @@ allocFunctions inst@ModuleInstance {types} funs =
getGlobalValue :: ModuleInstance -> Store -> Natural -> IO Value getGlobalValue :: ModuleInstance -> Store -> Natural -> IO Value
getGlobalValue inst store idx = getGlobalValue inst store idx =
let addr = globaladdrs inst ! fromIntegral idx in let addr = case globaladdrs inst !? fromIntegral idx of
Just a -> a
Nothing -> error "Global index is out of range. It can happen if initializer refs non-import global."
in
case globalInstances store ! addr of case globalInstances store ! addr of
GIConst v -> return v GIConst v -> return v
GIMut ref -> readIORef ref GIMut ref -> readIORef ref
allocGlobals :: ModuleInstance -> Store -> [Global] -> IO (Vector GlobalInstance) allocGlobals :: ModuleInstance -> Store -> [Global] -> IO (Vector GlobalInstance)
allocGlobals inst store globs = allocGlobals inst store globs = Vector.fromList <$> mapM allocGlob globs
let where
runIniter :: [Instruction] -> IO Value
-- due the validation there can be only these instructions -- due the validation there can be only these instructions
runIniter [I32Const v] = return $ VI32 v runIniter [I32Const v] = return $ VI32 v
runIniter [I64Const v] = return $ VI64 v runIniter [I64Const v] = return $ VI64 v
runIniter [F32Const v] = return $ VF32 v runIniter [F32Const v] = return $ VF32 v
runIniter [F64Const v] = return $ VF64 v runIniter [F64Const v] = return $ VF64 v
-- the spec says get global can ref only imported globals -- the spec says get global can ref only imported globals
-- it is implied by execution phase, but not validated in validation phase
runIniter [GetGlobal i] = getGlobalValue inst store i runIniter [GetGlobal i] = getGlobalValue inst store i
runIniter instrs = error $ "Global initializer contains unsupported instructions: " ++ show instrs runIniter instrs = error $ "Global initializer contains unsupported instructions: " ++ show instrs
in
let allocGlob :: Global -> IO GlobalInstance
allocGlob (Global (Const _) initer) = GIConst <$> runIniter initer allocGlob (Global (Const _) initer) = GIConst <$> runIniter initer
allocGlob (Global (Mut _) initer) = do allocGlob (Global (Mut _) initer) = do
val <- runIniter initer val <- runIniter initer
GIMut <$> newIORef val GIMut <$> newIORef val
in
Vector.fromList <$> mapM allocGlob globs
allocTables :: [Table] -> Vector TableInstance
allocTables tables = Vector.fromList $ map allocTable tables
where
allocTable :: Table -> TableInstance
allocTable (Table (TableType (Limit from to) _)) =
TableInstance {
elements = Vector.fromList $ replicate (fromIntegral from) Nothing,
maxLen = fromIntegral <$> to
}
allocMems :: [Memory] -> IO (Vector MemoryInstance)
allocMems mems = Vector.fromList <$> mapM allocMem mems
where
allocMem :: Memory -> IO MemoryInstance
allocMem (Memory (Limit from to)) = do
memory <- newArray (0, fromIntegral from * (16 * 1024{- 64 * 1024 bytes in Word32 -})) 0
return $ MemoryInstance {
memory,
maxLen = fromIntegral <$> to
}
instantiate :: Store -> Imports -> Module -> IO (ModuleInstance, Store) instantiate :: Store -> Imports -> Module -> IO (ModuleInstance, Store)
instantiate st imps m = do instantiate st imps m = do
let inst = calcInstance st imps m let inst = calcInstance st imps m
let funs = funcInstances st Vector.++ (allocFunctions inst $ Struct.functions m) let functions = funcInstances st Vector.++ (allocFunctions inst $ Struct.functions m)
globs <- (globalInstances st Vector.++) <$> (allocGlobals inst st $ Struct.globals m) globals <- (globalInstances st Vector.++) <$> (allocGlobals inst st $ Struct.globals m)
let tables = tableInstances st Vector.++ (allocTables $ Struct.tables m)
mems <- (memInstances st Vector.++) <$> (allocMems $ Struct.mems m)
let st' = st { let st' = st {
funcInstances = funs, funcInstances = functions,
globalInstances = globs tableInstances = tables,
memInstances = mems,
globalInstances = globals
} }
return $ (inst, st') return $ (inst, st')
-6
View File
@@ -581,12 +581,6 @@ exportsShouldBeValid Module { exports, imports, functions, mems, tables, globals
memImports = filter isMemImport imports memImports = filter isMemImport imports
globalImports = filter isGlobalImport imports globalImports = filter isGlobalImport imports
isFuncImport (Import _ _ (ImportFunc _)) = True
isFuncImport _ = False
isGlobalImport (Import _ _ (ImportGlobal _)) = True
isGlobalImport _ = False
isExportValid :: Export -> ValidationResult isExportValid :: Export -> ValidationResult
isExportValid (Export _ (ExportFunc funIdx)) = isExportValid (Export _ (ExportFunc funIdx)) =
isIndexValid funIdx $ length funcImports + length functions isIndexValid funIdx $ length funcImports + length functions