update go-ffmpreg to v0.3.1 (pulls in latest wazero too) (#3398)

This commit is contained in:
kim
2024-10-06 20:53:03 +00:00
committed by GitHub
parent 02470db5f6
commit bd1866ad8a
21 changed files with 190 additions and 180 deletions

View File

@ -1,6 +1,9 @@
package descriptor
import "math/bits"
import (
"math/bits"
"slices"
)
// Table is a data structure mapping 32 bit descriptor to items.
//
@ -37,23 +40,13 @@ func (t *Table[Key, Item]) Len() (n int) {
return n
}
// grow ensures that t has enough room for n items, potentially reallocating the
// internal buffers if their capacity was too small to hold this many items.
// grow grows the table by n * 64 items.
func (t *Table[Key, Item]) grow(n int) {
// Round up to a multiple of 64 since this is the smallest increment due to
// using 64 bits masks.
n = (n*64 + 63) / 64
total := len(t.masks) + n
t.masks = slices.Grow(t.masks, n)[:total]
if n > len(t.masks) {
masks := make([]uint64, n)
copy(masks, t.masks)
items := make([]Item, n*64)
copy(items, t.items)
t.masks = masks
t.items = items
}
total = len(t.items) + n*64
t.items = slices.Grow(t.items, n*64)[:total]
}
// Insert inserts the given item to the table, returning the key that it is
@ -78,13 +71,9 @@ insert:
}
}
// No free slot found, grow the table and retry.
offset = len(t.masks)
n := 2 * len(t.masks)
if n == 0 {
n = 1
}
t.grow(n)
t.grow(1)
goto insert
}
@ -109,10 +98,10 @@ func (t *Table[Key, Item]) InsertAt(item Item, key Key) bool {
if key < 0 {
return false
}
if diff := int(key) - t.Len(); diff > 0 {
index := uint(key) / 64
if diff := int(index) - len(t.masks) + 1; diff > 0 {
t.grow(diff)
}
index := uint(key) / 64
shift := uint(key) % 64
t.masks[index] |= 1 << shift
t.items[key] = item
@ -124,7 +113,8 @@ func (t *Table[Key, Item]) Delete(key Key) {
if key < 0 { // invalid key
return
}
if index, shift := key/64, key%64; int(index) < len(t.masks) {
if index := uint(key) / 64; int(index) < len(t.masks) {
shift := uint(key) % 64
mask := t.masks[index]
if (mask & (1 << shift)) != 0 {
var zero Item

View File

@ -487,7 +487,7 @@ func (e *engine) setLabelAddress(op *uint64, label label, labelAddressResolution
}
// ResolveImportedFunction implements wasm.ModuleEngine.
func (e *moduleEngine) ResolveImportedFunction(index, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) {
func (e *moduleEngine) ResolveImportedFunction(index, descFunc, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) {
imported := importedModuleEngine.(*moduleEngine)
e.functions[index] = imported.functions[indexInImportedModule]
}

View File

@ -237,7 +237,7 @@ func (m *moduleEngine) putLocalMemory() {
}
// ResolveImportedFunction implements wasm.ModuleEngine.
func (m *moduleEngine) ResolveImportedFunction(index, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) {
func (m *moduleEngine) ResolveImportedFunction(index, descFunc, indexInImportedModule wasm.Index, importedModuleEngine wasm.ModuleEngine) {
executableOffset, moduleCtxOffset, typeIDOffset := m.parent.offsets.ImportedFunctionOffset(index)
importedME := importedModuleEngine.(*moduleEngine)
@ -245,12 +245,12 @@ func (m *moduleEngine) ResolveImportedFunction(index, indexInImportedModule wasm
indexInImportedModule -= wasm.Index(len(importedME.importedFunctions))
} else {
imported := &importedME.importedFunctions[indexInImportedModule]
m.ResolveImportedFunction(index, imported.indexInModule, imported.me)
m.ResolveImportedFunction(index, descFunc, imported.indexInModule, imported.me)
return // Recursively resolve the imported function.
}
offset := importedME.parent.functionOffsets[indexInImportedModule]
typeID := getTypeIDOf(indexInImportedModule, importedME.module)
typeID := m.module.TypeIDs[descFunc]
executable := &importedME.parent.executable[offset]
// Write functionInstance.
binary.LittleEndian.PutUint64(m.opaque[executableOffset:], uint64(uintptr(unsafe.Pointer(executable))))
@ -261,28 +261,6 @@ func (m *moduleEngine) ResolveImportedFunction(index, indexInImportedModule wasm
m.importedFunctions[index] = importedFunction{me: importedME, indexInModule: indexInImportedModule}
}
func getTypeIDOf(funcIndex wasm.Index, m *wasm.ModuleInstance) wasm.FunctionTypeID {
source := m.Source
var typeIndex wasm.Index
if funcIndex >= source.ImportFunctionCount {
funcIndex -= source.ImportFunctionCount
typeIndex = source.FunctionSection[funcIndex]
} else {
var cnt wasm.Index
for i := range source.ImportSection {
if source.ImportSection[i].Type == wasm.ExternTypeFunc {
if cnt == funcIndex {
typeIndex = source.ImportSection[i].DescFunc
break
}
cnt++
}
}
}
return m.TypeIDs[typeIndex]
}
// ResolveImportedMemory implements wasm.ModuleEngine.
func (m *moduleEngine) ResolveImportedMemory(importedModuleEngine wasm.ModuleEngine) {
importedME := importedModuleEngine.(*moduleEngine)

View File

@ -5,6 +5,7 @@ package sysfs
import (
"io/fs"
"os"
"path"
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
)
@ -34,6 +35,11 @@ func (d *dirFS) Chmod(path string, perm fs.FileMode) experimentalsys.Errno {
// Symlink implements the same method as documented on sys.FS
func (d *dirFS) Symlink(oldName, link string) experimentalsys.Errno {
// Creating a symlink with an absolute path string fails with a "not permitted" error.
// https://github.com/WebAssembly/wasi-filesystem/blob/v0.2.0/path-resolution.md#symlinks
if path.IsAbs(oldName) {
return experimentalsys.EPERM
}
// Note: do not resolve `oldName` relative to this dirFS. The link result is always resolved
// when dereference the `link` on its usage (e.g. readlink, read, etc).
// https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409

View File

@ -269,7 +269,7 @@ func (f *fsFile) Readdir(n int) (dirents []experimentalsys.Dirent, errno experim
if f.reopenDir { // re-open the directory if needed.
f.reopenDir = false
if errno = adjustReaddirErr(f, f.closed, f.reopen()); errno != 0 {
if errno = adjustReaddirErr(f, f.closed, f.rewindDir()); errno != 0 {
return
}
}
@ -418,19 +418,25 @@ func seek(s io.Seeker, offset int64, whence int) (int64, experimentalsys.Errno)
return newOffset, experimentalsys.UnwrapOSError(err)
}
// reopenFile allows re-opening a file for reasons such as applying flags or
// directory iteration.
type reopenFile func() experimentalsys.Errno
// compile-time check to ensure fsFile.reopen implements reopenFile.
var _ reopenFile = (*fsFile)(nil).reopen
// reopen implements the same method as documented on reopenFile.
func (f *fsFile) reopen() experimentalsys.Errno {
_ = f.close()
var err error
f.file, err = f.fs.Open(f.name)
return experimentalsys.UnwrapOSError(err)
func (f *fsFile) rewindDir() experimentalsys.Errno {
// Reopen the directory to rewind it.
file, err := f.fs.Open(f.name)
if err != nil {
return experimentalsys.UnwrapOSError(err)
}
fi, err := file.Stat()
if err != nil {
return experimentalsys.UnwrapOSError(err)
}
// Can't check if it's still the same file,
// but is it still a directory, at least?
if !fi.IsDir() {
return experimentalsys.ENOTDIR
}
// Only update f on success.
_ = f.file.Close()
f.file = file
return 0
}
// readdirFile allows masking the `Readdir` function on os.File.

View File

@ -83,21 +83,12 @@ func (f *osFile) SetAppend(enable bool) (errno experimentalsys.Errno) {
f.flag &= ^experimentalsys.O_APPEND
}
// Clear any create or trunc flag, as we are re-opening, not re-creating.
f.flag &= ^(experimentalsys.O_CREAT | experimentalsys.O_TRUNC)
// appendMode (bool) cannot be changed later, so we have to re-open the
// file. https://github.com/golang/go/blob/go1.20/src/os/file_unix.go#L60
// appendMode cannot be changed later, so we have to re-open the file
// https://github.com/golang/go/blob/go1.23/src/os/file_unix.go#L60
return fileError(f, f.closed, f.reopen())
}
// compile-time check to ensure osFile.reopen implements reopenFile.
var _ reopenFile = (*osFile)(nil).reopen
func (f *osFile) reopen() (errno experimentalsys.Errno) {
// Clear any create flag, as we are re-opening, not re-creating.
f.flag &= ^experimentalsys.O_CREAT
var (
isDir bool
offset int64
@ -116,22 +107,47 @@ func (f *osFile) reopen() (errno experimentalsys.Errno) {
}
}
_ = f.close()
f.file, errno = OpenFile(f.path, f.flag, f.perm)
// Clear any create or trunc flag, as we are re-opening, not re-creating.
flag := f.flag &^ (experimentalsys.O_CREAT | experimentalsys.O_TRUNC)
file, errno := OpenFile(f.path, flag, f.perm)
if errno != 0 {
return errno
}
errno = f.checkSameFile(file)
if errno != 0 {
return errno
}
if !isDir {
_, err = f.file.Seek(offset, io.SeekStart)
_, err = file.Seek(offset, io.SeekStart)
if err != nil {
_ = file.Close()
return experimentalsys.UnwrapOSError(err)
}
}
// Only update f on success.
_ = f.file.Close()
f.file = file
f.fd = file.Fd()
return 0
}
func (f *osFile) checkSameFile(osf *os.File) experimentalsys.Errno {
fi1, err := f.file.Stat()
if err != nil {
return experimentalsys.UnwrapOSError(err)
}
fi2, err := osf.Stat()
if err != nil {
return experimentalsys.UnwrapOSError(err)
}
if os.SameFile(fi1, fi2) {
return 0
}
return experimentalsys.ENOENT
}
// IsNonblock implements the same method as documented on fsapi.File
func (f *osFile) IsNonblock() bool {
return isNonblock(f)

View File

@ -44,9 +44,10 @@ type ModuleEngine interface {
// ResolveImportedFunction is used to add imported functions needed to make this ModuleEngine fully functional.
// - `index` is the function Index of this imported function.
// - `descFunc` is the type Index in Module.TypeSection of this imported function. It corresponds to Import.DescFunc.
// - `indexInImportedModule` is the function Index of the imported function in the imported module.
// - `importedModuleEngine` is the ModuleEngine for the imported ModuleInstance.
ResolveImportedFunction(index, indexInImportedModule Index, importedModuleEngine ModuleEngine)
ResolveImportedFunction(index, descFunc, indexInImportedModule Index, importedModuleEngine ModuleEngine)
// ResolveImportedMemory is called when this module imports a memory from another module.
ResolveImportedMemory(importedModuleEngine ModuleEngine)

View File

@ -77,6 +77,7 @@ func NewMemoryInstance(memSec *Memory, allocator experimental.MemoryAllocator, m
if allocator != nil {
expBuffer = allocator.Allocate(capBytes, maxBytes)
buffer = expBuffer.Reallocate(minBytes)
_ = buffer[:minBytes] // Bounds check that the minimum was allocated.
} else if memSec.IsShared {
// Shared memory needs a fixed buffer, so allocate with the maximum size.
//
@ -238,12 +239,15 @@ func (m *MemoryInstance) Grow(delta uint32) (result uint32, ok bool) {
return currentPages, true
}
// If exceeds the max of memory size, we push -1 according to the spec.
newPages := currentPages + delta
if newPages > m.Max || int32(delta) < 0 {
return 0, false
} else if m.expBuffer != nil {
buffer := m.expBuffer.Reallocate(MemoryPagesToBytesNum(newPages))
if buffer == nil {
// Allocator failed to grow.
return 0, false
}
if m.Shared {
if unsafe.SliceData(buffer) != unsafe.SliceData(m.Buffer) {
panic("shared memory cannot move, this is a bug in the memory allocator")

View File

@ -446,7 +446,7 @@ func (m *ModuleInstance) resolveImports(ctx context.Context, module *Module) (er
return
}
m.Engine.ResolveImportedFunction(i.IndexPerType, imported.Index, importedModule.Engine)
m.Engine.ResolveImportedFunction(i.IndexPerType, i.DescFunc, imported.Index, importedModule.Engine)
case ExternTypeTable:
expected := i.DescTable
importedTable := importedModule.Tables[imported.Index]