1
1
mirror of https://github.com/tweag/asterius.git synced 2024-09-21 05:48:04 +03:00

Use imported table for asterius instances (#91)

This commit is contained in:
Shao Cheng 2019-03-16 16:57:19 +08:00 committed by GitHub
parent e29560ef33
commit f926cc60d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 144 additions and 117 deletions

View File

@ -22,7 +22,8 @@ export function newAsteriusInstance(req) {
let __asterius_logger = new EventLogManager(req.symbolTable),
__asterius_tracer = new Tracer(__asterius_logger, req.symbolTable),
__asterius_wasm_instance = null,
__asterius_wasm_memory = new WebAssembly.Memory({initial: req.staticMBlocks * (settings.mblock_size / 65536), maximum: 65536}),
__asterius_wasm_table = new WebAssembly.Table({element: "anyfunc", initial: req.tableSlots}),
__asterius_wasm_memory = new WebAssembly.Memory({initial: req.staticMBlocks * (settings.mblock_size / 65536)}),
__asterius_memory = new Memory(),
__asterius_memory_trap = new MemoryTrap(__asterius_logger, req.symbolTable),
__asterius_mblockalloc = new MBlockAlloc(),
@ -109,6 +110,9 @@ export function newAsteriusInstance(req) {
exp: x => Math.exp(x),
pow: (x, y) => Math.pow(x, y)
},
WasmTable: {
table: __asterius_wasm_table
},
WasmMemory: {
memory: __asterius_wasm_memory
},

View File

@ -896,11 +896,7 @@ stgRun init_f = do
putLVal f init_f
loop' [] $ \loop_lbl ->
if' [] (eqZInt64 (getLVal f)) mempty $ do
f' <-
callIndirect'
(getLVal f `subInt64` constI64 1)
[]
(FunctionType [] [I64])
f' <- callIndirect' (getLVal f) [] (FunctionType [] [I64])
putLVal f f'
break' loop_lbl Nothing
pure $ getLVal r1

View File

@ -330,6 +330,8 @@ genLib Task {..} LinkReport {..} err_msgs =
staticsSymbolMap
exportFunctions
bundledFFIMarshalState
, ", tableSlots: "
, intDec tableSlots
, ", staticMBlocks: "
, intDec staticMBlocks
, if sync
@ -486,6 +488,10 @@ ahcDistMain task@Task {..} (final_m, err_msgs, report) = do
c_BinaryenSetShrinkLevel 0
m_ref <-
withPool $ \pool -> OldMarshal.marshalModule pool final_m
putStrLn "[INFO] Validating binaryen IR"
pass_validation <- c_BinaryenModuleValidate m_ref
when (pass_validation /= 1) $
fail "[ERROR] binaryen validation failed"
m_bin <- LBS.fromStrict <$> OldMarshal.serializeModule m_ref
putStrLn $
"[INFO] Writing WebAssembly binary to " <> show out_wasm

View File

@ -26,6 +26,7 @@ import Data.Traversable
import Foreign hiding (void)
import Foreign.C
import GHC.Exts
import Language.Haskell.GHC.Toolkit.Constants
import Prelude hiding (IO)
newtype MarshalError =
@ -332,46 +333,64 @@ marshalFunctionExport pool m FunctionExport {..} = do
enp <- marshalSBS pool externalName
c_BinaryenAddFunctionExport m inp enp
marshalFunctionTable :: Pool -> BinaryenModuleRef -> FunctionTable -> IO ()
marshalFunctionTable pool m FunctionTable {..} = do
func_name_ptrs <- for functionNames $ marshalSBS pool
marshalFunctionTable ::
Pool -> BinaryenModuleRef -> Int -> FunctionTable -> IO ()
marshalFunctionTable pool m tbl_slots FunctionTable {..} = do
func_name_ptrs <- for tableFunctionNames $ marshalSBS pool
(fnp, fnl) <- marshalV pool func_name_ptrs
let l = fromIntegral $ length functionNames
c_BinaryenSetFunctionTable m l (-1) fnp fnl
tbl_name <- marshalSBS pool tableExportName
unless (tbl_name == nullPtr) $ do
tbl_internal_name <- marshalSBS pool "0"
void $ c_BinaryenAddMemoryExport m tbl_internal_name tbl_name
c_BinaryenSetFunctionTableWithOffset
m
(fromIntegral tbl_slots)
(-1)
tableOffset
fnp
fnl
marshalMemorySegments :: Pool -> BinaryenModuleRef -> [DataSegment] -> IO ()
marshalMemorySegments pool m segs = do
marshalMemorySegments ::
Pool -> BinaryenModuleRef -> Int -> [DataSegment] -> IO ()
marshalMemorySegments pool m mbs segs = do
(seg_bufs, _ :: Int) <- marshalV pool =<< for segs (marshalSBS pool . content)
(seg_offsets, _ :: Int) <-
marshalV pool =<<
for segs (\DataSegment {..} -> marshalExpression pool m $ ConstI32 offset)
(seg_sizes, _ :: Int) <-
marshalV pool $ map (fromIntegral . SBS.length . content) segs
c_BinaryenAddSegments
c_BinaryenSetMemory
m
(fromIntegral $ mbs * (mblock_size `quot` 65536))
(-1)
nullPtr
seg_bufs
seg_offsets
seg_sizes
(fromIntegral $ length segs)
0
marshalTableImport :: Pool -> BinaryenModuleRef -> TableImport -> IO ()
marshalTableImport pool m TableImport {..} = do
inp <- marshalSBS pool "0"
emp <- marshalSBS pool externalModuleName
ebp <- marshalSBS pool externalBaseName
c_BinaryenAddTableImport m inp emp ebp
marshalMemoryImport :: Pool -> BinaryenModuleRef -> MemoryImport -> IO ()
marshalMemoryImport pool m MemoryImport {..} = do
inp <- marshalSBS pool internalName
inp <- marshalSBS pool "0"
emp <- marshalSBS pool externalModuleName
ebp <- marshalSBS pool externalBaseName
c_BinaryenAddMemoryImport m inp emp ebp $
if shared
then 1
else 0
c_BinaryenAddMemoryImport m inp emp ebp 0
marshalTableExport ::
Pool -> BinaryenModuleRef -> TableExport -> IO BinaryenExportRef
marshalTableExport pool m TableExport {..} = do
inp <- marshalSBS pool "0"
enp <- marshalSBS pool externalName
c_BinaryenAddTableExport m inp enp
marshalMemoryExport ::
Pool -> BinaryenModuleRef -> MemoryExport -> IO BinaryenExportRef
marshalMemoryExport pool m MemoryExport {..} = do
inp <- marshalSBS pool internalName
inp <- marshalSBS pool "0"
enp <- marshalSBS pool externalName
c_BinaryenAddMemoryExport m inp enp
@ -389,8 +408,10 @@ marshalModule pool hs_mod@Module {..} = do
forM_ functionImports $ \fi@FunctionImport {..} ->
marshalFunctionImport pool m (ftps ! functionType) fi
forM_ functionExports $ marshalFunctionExport pool m
marshalFunctionTable pool m functionTable
marshalMemorySegments pool m memorySegments
marshalFunctionTable pool m tableSlots functionTable
marshalTableImport pool m tableImport
void $ marshalTableExport pool m tableExport
marshalMemorySegments pool m memoryMBlocks memorySegments
marshalMemoryImport pool m memoryImport
void $ marshalMemoryExport pool m memoryExport
pure m

View File

@ -102,6 +102,17 @@ makeImportSection Module {..} ModuleSymbolTable {..} =
, maxLimit = Nothing
}
}) :
(case tableImport of
TableImport {..} ->
Wasm.Import
{ moduleName = coerce externalModuleName
, importName = coerce externalBaseName
, importDescription =
Wasm.ImportTable $
Wasm.TableType Wasm.AnyFunc $
Wasm.Limits
{minLimit = fromIntegral tableSlots, maxLimit = Nothing}
}) :
[ Wasm.Import
{ moduleName = coerce externalModuleName
, importName = coerce externalBaseName
@ -123,27 +134,6 @@ makeFunctionSection Module {..} ModuleSymbolTable {..} =
]
}
makeTableSection :: MonadError MarshalError m => Module -> m Wasm.Section
makeTableSection Module {..} =
pure
Wasm.TableSection
{ tables =
[ Wasm.Table
{ tableType =
Wasm.TableType
{ elementType = Wasm.AnyFunc
, tableLimits =
Wasm.Limits
{ minLimit =
fromIntegral $
length $ functionNames functionTable
, maxLimit = Nothing
}
}
}
]
}
makeExportSection ::
MonadError MarshalError m => Module -> ModuleSymbolTable -> m Wasm.Section
makeExportSection Module {..} ModuleSymbolTable {..} =
@ -164,15 +154,13 @@ makeExportSection Module {..} ModuleSymbolTable {..} =
, exportDescription = Wasm.ExportMemory $ Wasm.MemoryIndex 0
}
]) <>
(case functionTable of
FunctionTable {..}
| not $ SBS.null tableExportName ->
[ Wasm.Export
{ exportName = coerce tableExportName
, exportDescription = Wasm.ExportTable $ Wasm.TableIndex 0
}
]
| otherwise -> [])
(case tableExport of
TableExport {..} ->
[ Wasm.Export
{ exportName = coerce externalName
, exportDescription = Wasm.ExportTable $ Wasm.TableIndex 0
}
])
}
makeElementSection ::
@ -187,9 +175,15 @@ makeElementSection Module {..} ModuleSymbolTable {..} =
{ tableIndex = Wasm.TableIndex 0
, tableOffset =
Wasm.Expression
{instructions = [Wasm.I32Const {i32ConstValue = 0}]}
{ instructions =
[ Wasm.I32Const
{i32ConstValue = fromIntegral tableOffset}
]
}
, tableInitialValues =
[functionSymbols ! _func_sym | _func_sym <- functionNames]
[ functionSymbols ! _func_sym
| _func_sym <- tableFunctionNames
]
}
]
}
@ -623,7 +617,6 @@ makeModule m = do
_type_sec <- makeTypeSection m _module_symtable
_import_sec <- makeImportSection m _module_symtable
_func_sec <- makeFunctionSection m _module_symtable
_table_sec <- makeTableSection m
_export_sec <- makeExportSection m _module_symtable
_elem_sec <- makeElementSection m _module_symtable
_code_sec <- makeCodeSection m _module_symtable
@ -633,7 +626,6 @@ makeModule m = do
[ _type_sec
, _import_sec
, _func_sec
, _table_sec
, _export_sec
, _elem_sec
, _code_sec

View File

@ -1,5 +1,3 @@
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Asterius.Passes.FunctionSymbolTable
@ -8,30 +6,23 @@ module Asterius.Passes.FunctionSymbolTable
) where
import Asterius.Types
import Data.Bits
import Data.Coerce
import qualified Data.IntMap.Strict as IMap
import Data.Int
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Tuple
import GHC.Exts
import GHC.Int
{-# INLINABLE makeFunctionSymbolTable #-}
makeFunctionSymbolTable ::
AsteriusModule -> Int64 -> (Map AsteriusEntitySymbol Int64, Int64)
makeFunctionSymbolTable AsteriusModule {..} l =
swap $ Map.mapAccum (\a _ -> (succ a, a)) l functionMap
makeFunctionSymbolTable AsteriusModule {..} func_start_addr =
swap $ Map.mapAccum (\a _ -> (succ a, a)) func_start_addr functionMap
{-# INLINABLE makeFunctionTable #-}
makeFunctionTable :: Map AsteriusEntitySymbol Int64 -> FunctionTable
makeFunctionTable sym_map =
makeFunctionTable :: Map AsteriusEntitySymbol Int64 -> Int64 -> FunctionTable
makeFunctionTable func_sym_map func_start_addr =
FunctionTable
{ functionNames =
coerce $
IMap.elems $
Map.foldlWithKey'
(\tot sym (I64# addr) -> IMap.insert (I# addr) sym tot)
IMap.empty
sym_map
, tableExportName = "table"
{ tableFunctionNames = coerce $ Map.keys func_sym_map
, tableOffset = fromIntegral $ func_start_addr .&. 0xFFFFFFFF
}

View File

@ -51,7 +51,7 @@ data LinkReport = LinkReport
{ unavailableSymbols :: S.Set AsteriusEntitySymbol
, staticsSymbolMap, functionSymbolMap :: LM.Map AsteriusEntitySymbol Int64
, infoTableSet :: S.Set Int64
, staticMBlocks :: Int
, tableSlots, staticMBlocks :: Int
, bundledFFIMarshalState :: FFIMarshalState
} deriving (Generic, Show)
@ -64,6 +64,7 @@ instance Semigroup LinkReport where
, staticsSymbolMap = staticsSymbolMap r0 <> staticsSymbolMap r1
, functionSymbolMap = functionSymbolMap r0 <> functionSymbolMap r1
, infoTableSet = infoTableSet r0 <> infoTableSet r1
, tableSlots = 0
, staticMBlocks = 0
, bundledFFIMarshalState =
bundledFFIMarshalState r0 <> bundledFFIMarshalState r1
@ -76,6 +77,7 @@ instance Monoid LinkReport where
, staticsSymbolMap = mempty
, functionSymbolMap = mempty
, infoTableSet = mempty
, tableSlots = 0
, staticMBlocks = 0
, bundledFFIMarshalState = mempty
}
@ -177,14 +179,16 @@ resolveAsteriusModule ::
, LM.Map AsteriusEntitySymbol Int64
, LM.Map AsteriusEntitySymbol Int64
, [Event]
, Int
, Int)
resolveAsteriusModule debug has_main bundled_ffi_state export_funcs m_globals_resolved func_start_addr data_start_addr =
(new_mod, ss_sym_map, func_sym_map, err_msgs, initial_mblocks)
(new_mod, ss_sym_map, func_sym_map, err_msgs, table_slots, initial_mblocks)
where
(func_sym_map, _) =
(func_sym_map, last_func_addr) =
makeFunctionSymbolTable m_globals_resolved func_start_addr
func_table = makeFunctionTable func_sym_map
(ss_sym_map, last_addr) =
table_slots = fromIntegral $ last_func_addr .&. 0xFFFFFFFF
func_table = makeFunctionTable func_sym_map func_start_addr
(ss_sym_map, last_data_addr) =
makeDataSymbolTable m_globals_resolved data_start_addr
all_sym_map = func_sym_map <> ss_sym_map
func_imports =
@ -210,7 +214,8 @@ resolveAsteriusModule debug has_main bundled_ffi_state export_funcs m_globals_re
, body = body_locals_resolved
}
, event_map')
(initial_pages, segs) = makeMemory m_globals_resolved all_sym_map last_addr
(initial_pages, segs) =
makeMemory m_globals_resolved all_sym_map last_data_addr
initial_mblocks =
fromIntegral initial_pages `quot` (mblock_size `quot` wasmPageSize)
new_mod =
@ -224,17 +229,16 @@ resolveAsteriusModule debug has_main bundled_ffi_state export_funcs m_globals_re
| k <- map entityName export_funcs
]
, functionTable = func_table
, tableImport =
TableImport
{externalModuleName = "WasmTable", externalBaseName = "table"}
, tableExport = TableExport {externalName = "table"}
, tableSlots = table_slots
, memorySegments = segs
, memoryImport =
MemoryImport
{ internalName = "__asterius_memory"
, externalModuleName = "WasmMemory"
, externalBaseName = "memory"
, shared = False
}
, memoryExport =
MemoryExport
{internalName = "__asterius_memory", externalName = "memory"}
{externalModuleName = "WasmMemory", externalBaseName = "memory"}
, memoryExport = MemoryExport {externalName = "memory"}
, memoryMBlocks = initial_mblocks
}
err_msgs = eventTable all_event_map
@ -253,6 +257,7 @@ linkStart debug has_main store root_syms export_funcs =
{ staticsSymbolMap = ss_sym_map
, functionSymbolMap = func_sym_map
, infoTableSet = makeInfoTableSet merged_m ss_sym_map
, Asterius.Resolve.tableSlots = tbl_slots
, staticMBlocks = static_mbs
})
where
@ -266,7 +271,7 @@ linkStart debug has_main store root_syms export_funcs =
{entityName = "__asterius_jsffi_export_" <> entityName k}
| k <- export_funcs
])
(result_m, ss_sym_map, func_sym_map, err_msgs, static_mbs) =
(result_m, ss_sym_map, func_sym_map, err_msgs, tbl_slots, static_mbs) =
resolveAsteriusModule
debug
has_main

View File

@ -28,8 +28,10 @@ module Asterius.Types
, Expression(..)
, Function(..)
, FunctionImport(..)
, TableImport(..)
, MemoryImport(..)
, FunctionExport(..)
, TableExport(..)
, MemoryExport(..)
, FunctionTable(..)
, DataSegment(..)
@ -425,9 +427,14 @@ data FunctionImport = FunctionImport
instance Binary FunctionImport
data TableImport = TableImport
{ externalModuleName, externalBaseName :: SBS.ShortByteString
} deriving (Eq, Show, Data, Generic)
instance Binary TableImport
data MemoryImport = MemoryImport
{ internalName, externalModuleName, externalBaseName :: SBS.ShortByteString
, shared :: Bool
{ externalModuleName, externalBaseName :: SBS.ShortByteString
} deriving (Eq, Show, Data, Generic)
instance Binary MemoryImport
@ -438,15 +445,21 @@ data FunctionExport = FunctionExport
instance Binary FunctionExport
data MemoryExport = MemoryExport
{ internalName, externalName :: SBS.ShortByteString
newtype TableExport = TableExport
{ externalName :: SBS.ShortByteString
} deriving (Eq, Show, Data, Generic)
instance Binary TableExport
newtype MemoryExport = MemoryExport
{ externalName :: SBS.ShortByteString
} deriving (Eq, Show, Data, Generic)
instance Binary MemoryExport
data FunctionTable = FunctionTable
{ functionNames :: [SBS.ShortByteString]
, tableExportName :: SBS.ShortByteString
{ tableFunctionNames :: [SBS.ShortByteString]
, tableOffset :: BinaryenIndex
} deriving (Eq, Show, Data, Generic)
instance Binary FunctionTable
@ -463,6 +476,9 @@ data Module = Module
, functionImports :: [FunctionImport]
, functionExports :: [FunctionExport]
, functionTable :: FunctionTable
, tableImport :: TableImport
, tableExport :: TableExport
, tableSlots :: Int
, memorySegments :: [DataSegment]
, memoryImport :: MemoryImport
, memoryExport :: MemoryExport

View File

@ -2342,7 +2342,12 @@ void BinaryenRemoveExport(BinaryenModuleRef module, const char* externalName) {
// Function table. One per module
void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char** funcNames, BinaryenIndex numFuncNames) {
void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial,
BinaryenIndex maximum, const char** funcNames, BinaryenIndex numFuncNames) {
BinaryenSetFunctionTableWithOffset(module, initial, maximum, 0, funcNames, numFuncNames);
}
void BinaryenSetFunctionTableWithOffset(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, BinaryenIndex offset, const char** funcNames, BinaryenIndex numFuncNames) {
if (tracing) {
std::cout << " {\n";
std::cout << " const char* funcNames[] = { ";
@ -2356,7 +2361,7 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, B
}
auto* wasm = (Module*)module;
Table::Segment segment(wasm->allocator.alloc<Const>()->set(Literal(int32_t(0))));
Table::Segment segment(wasm->allocator.alloc<Const>()->set(Literal(int32_t(offset))));
for (BinaryenIndex i = 0; i < numFuncNames; i++) {
segment.data.push_back(funcNames[i]);
}
@ -2423,15 +2428,6 @@ void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, Binaryen
}
}
void BinaryenAddSegments(BinaryenModuleRef module, const char** segments,
BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments) {
auto* wasm = (Module*)module;
for (BinaryenIndex i = 0; i < numSegments; i++) {
wasm->memory.segments.emplace_back(
(Expression*)segmentOffsets[i], segments[i], segmentSizes[i]);
}
}
// Start function. One per module
void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) {

View File

@ -748,14 +748,14 @@ void BinaryenRemoveGlobal(BinaryenModuleRef module, const char* name);
void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char** funcNames, BinaryenIndex numFuncNames);
void BinaryenSetFunctionTableWithOffset(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, BinaryenIndex offset, const char** funcNames, BinaryenIndex numFuncNames);
// Memory. One per module
// Each segment has data in segments, a start offset in segmentOffsets, and a size in segmentSizes.
// exportName can be NULL
void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, uint8_t shared);
void BinaryenAddSegments(BinaryenModuleRef module, const char** segments, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments);
// Start function. One per module
void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start);

View File

@ -1600,6 +1600,12 @@ foreign import ccall unsafe "BinaryenSetFunctionTable" c_BinaryenSetFunctionTabl
BinaryenIndex ->
BinaryenIndex -> Ptr (Ptr CChar) -> BinaryenIndex -> IO ()
foreign import ccall unsafe "BinaryenSetFunctionTableWithOffset" c_BinaryenSetFunctionTableWithOffset
:: BinaryenModuleRef ->
BinaryenIndex ->
BinaryenIndex ->
BinaryenIndex -> Ptr (Ptr CChar) -> BinaryenIndex -> IO ()
foreign import ccall unsafe "BinaryenSetMemory" c_BinaryenSetMemory
:: BinaryenModuleRef ->
BinaryenIndex ->
@ -1609,12 +1615,6 @@ foreign import ccall unsafe "BinaryenSetMemory" c_BinaryenSetMemory
Ptr BinaryenExpressionRef ->
Ptr BinaryenIndex -> BinaryenIndex -> Word8 -> IO ()
foreign import ccall unsafe "BinaryenAddSegments" c_BinaryenAddSegments
:: BinaryenModuleRef ->
Ptr (Ptr CChar) ->
Ptr BinaryenExpressionRef ->
Ptr BinaryenIndex -> BinaryenIndex -> IO ()
foreign import ccall unsafe "BinaryenSetStart" c_BinaryenSetStart
:: BinaryenModuleRef -> BinaryenFunctionRef -> IO ()