Adds Runtime.WithCapacityPages to avoid allocations during runtime. (#514)
`Runtime.WithMemoryCapacityPages` is a function that determines memory
capacity in pages (65536 bytes per page). The inputs are the min and
possibly nil max defined by the module, and the default is to return
the min.
Ex. To set capacity to max when exists:
```golang
c.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
if maxPages != nil {
return *maxPages
}
return minPages
})
```
Note: This applies at compile time, ModuleBuilder.Build or Runtime.CompileModule.
Fixes #500
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
52
wasm.go
52
wasm.go
@@ -124,17 +124,19 @@ func NewRuntime() Runtime {
|
||||
// NewRuntimeWithConfig returns a runtime with the given configuration.
|
||||
func NewRuntimeWithConfig(config *RuntimeConfig) Runtime {
|
||||
return &runtime{
|
||||
store: wasm.NewStore(config.enabledFeatures, config.newEngine(config.enabledFeatures)),
|
||||
enabledFeatures: config.enabledFeatures,
|
||||
memoryMaxPages: config.memoryMaxPages,
|
||||
store: wasm.NewStore(config.enabledFeatures, config.newEngine(config.enabledFeatures)),
|
||||
enabledFeatures: config.enabledFeatures,
|
||||
memoryLimitPages: config.memoryLimitPages,
|
||||
memoryCapacityPages: config.memoryCapacityPages,
|
||||
}
|
||||
}
|
||||
|
||||
// runtime allows decoupling of public interfaces from internal representation.
|
||||
type runtime struct {
|
||||
enabledFeatures wasm.Features
|
||||
store *wasm.Store
|
||||
memoryMaxPages uint32
|
||||
enabledFeatures wasm.Features
|
||||
store *wasm.Store
|
||||
memoryLimitPages uint32
|
||||
memoryCapacityPages func(minPages uint32, maxPages *uint32) uint32
|
||||
}
|
||||
|
||||
// Module implements Runtime.Module
|
||||
@@ -160,13 +162,14 @@ func (r *runtime) CompileModule(ctx context.Context, source []byte) (*CompiledCo
|
||||
decoder = text.DecodeModule
|
||||
}
|
||||
|
||||
if r.memoryMaxPages > wasm.MemoryMaxPages {
|
||||
return nil, fmt.Errorf("memoryMaxPages %d (%s) > specification max %d (%s)",
|
||||
r.memoryMaxPages, wasm.PagesToUnitOfBytes(r.memoryMaxPages),
|
||||
wasm.MemoryMaxPages, wasm.PagesToUnitOfBytes(wasm.MemoryMaxPages))
|
||||
if r.memoryLimitPages > wasm.MemoryLimitPages {
|
||||
return nil, fmt.Errorf("memoryLimitPages %d (%s) > specification max %d (%s)",
|
||||
r.memoryLimitPages, wasm.PagesToUnitOfBytes(r.memoryLimitPages),
|
||||
wasm.MemoryLimitPages, wasm.PagesToUnitOfBytes(wasm.MemoryLimitPages))
|
||||
}
|
||||
|
||||
internal, err := decoder(source, r.enabledFeatures, r.memoryMaxPages)
|
||||
internal, err := decoder(source, r.enabledFeatures, r.memoryLimitPages)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = internal.Validate(r.enabledFeatures); err != nil {
|
||||
@@ -175,6 +178,20 @@ func (r *runtime) CompileModule(ctx context.Context, source []byte) (*CompiledCo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine the correct memory capacity, if a memory was defined.
|
||||
if mem := internal.MemorySection; mem != nil {
|
||||
memoryName := "0"
|
||||
for _, e := range internal.ExportSection {
|
||||
if e.Type == wasm.ExternTypeMemory {
|
||||
memoryName = e.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
if err = r.setMemoryCapacity(memoryName, mem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
internal.AssignModuleID(source)
|
||||
|
||||
if err = r.store.Engine.CompileModule(ctx, internal); err != nil {
|
||||
@@ -252,3 +269,16 @@ func (r *runtime) InstantiateModuleWithConfig(ctx context.Context, compiled *Com
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// setMemoryCapacity sets wasm.Memory cap using the function supplied by RuntimeConfig.WithMemoryCapacityPages.
|
||||
func (r *runtime) setMemoryCapacity(name string, mem *wasm.Memory) error {
|
||||
var max *uint32
|
||||
if mem.IsMaxEncoded {
|
||||
max = &mem.Max
|
||||
}
|
||||
mem.Cap = r.memoryCapacityPages(mem.Min, max)
|
||||
if err := mem.ValidateCap(r.memoryLimitPages); err != nil {
|
||||
return fmt.Errorf("memory[%s] %v", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user