all: make WebAssembly initial linear memory size configurable

When the target supports it, allow the (initial) heap size to be
configured. Currently only supported in WebAssembly.

This also changes the default heap size of WebAssembly from 64kB to 1MB.
Этот коммит содержится в:
Ayke van Laethem 2019-07-07 19:43:46 +02:00 коммит произвёл Ron Evans
родитель 152caa3b0a
коммит d627208c48
2 изменённых файлов: 44 добавлений и 2 удалений

41
main.go
Просмотреть файл

@ -55,6 +55,7 @@ type BuildConfig struct {
ldFlags []string ldFlags []string
tags string tags string
wasmAbi string wasmAbi string
heapSize int64
testConfig compiler.TestConfig testConfig compiler.TestConfig
} }
@ -240,10 +241,16 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
// Prepare link command. // Prepare link command.
executable := filepath.Join(dir, "main") executable := filepath.Join(dir, "main")
tmppath := executable // final file tmppath := executable // final file
ldflags := append(ldflags, "-o", executable, objfile, "-L", root) ldflags = append(ldflags, "-o", executable, objfile, "-L", root)
if spec.RTLib == "compiler-rt" { if spec.RTLib == "compiler-rt" {
ldflags = append(ldflags, librt) ldflags = append(ldflags, librt)
} }
if spec.GOARCH == "wasm" {
// Round heap size to next multiple of 65536 (the WebAssembly page
// size).
heapSize := (config.heapSize + (65536 - 1)) &^ (65536 - 1)
ldflags = append(ldflags, "--initial-memory="+strconv.FormatInt(heapSize, 10))
}
// Compile extra files. // Compile extra files.
for i, path := range spec.ExtraFiles { for i, path := range spec.ExtraFiles {
@ -540,6 +547,30 @@ func Run(pkgName, target string, config *BuildConfig) error {
}) })
} }
// parseSize converts a human-readable size (with k/m/g suffix) into a plain
// number.
func parseSize(s string) (int64, error) {
s = strings.ToLower(strings.TrimSpace(s))
if len(s) == 0 {
return 0, errors.New("no size provided")
}
multiply := int64(1)
switch s[len(s)-1] {
case 'k':
multiply = 1 << 10
case 'm':
multiply = 1 << 20
case 'g':
multiply = 1 << 30
}
if multiply != 1 {
s = s[:len(s)-1]
}
n, err := strconv.ParseInt(s, 0, 64)
n *= multiply
return n, err
}
func usage() { func usage() {
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.") fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
fmt.Fprintln(os.Stderr, "version:", version) fmt.Fprintln(os.Stderr, "version:", version)
@ -598,6 +629,7 @@ func main() {
cFlags := flag.String("cflags", "", "additional cflags for compiler") cFlags := flag.String("cflags", "", "additional cflags for compiler")
ldFlags := flag.String("ldflags", "", "additional ldflags for linker") ldFlags := flag.String("ldflags", "", "additional ldflags for linker")
wasmAbi := flag.String("wasm-abi", "js", "WebAssembly ABI conventions: js (no i64 params) or generic") wasmAbi := flag.String("wasm-abi", "js", "WebAssembly ABI conventions: js (no i64 params) or generic")
heapSize := flag.String("heap-size", "1M", "default heap size in bytes (only supported by WebAssembly)")
if len(os.Args) < 2 { if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "No command-line arguments supplied.") fmt.Fprintln(os.Stderr, "No command-line arguments supplied.")
@ -633,6 +665,13 @@ func main() {
os.Exit(1) os.Exit(1)
} }
var err error
if config.heapSize, err = parseSize(*heapSize); err != nil {
fmt.Fprintln(os.Stderr, "Could not read heap size:", *heapSize)
usage()
os.Exit(1)
}
os.Setenv("CC", "clang -target="+*target) os.Setenv("CC", "clang -target="+*target)
switch command { switch command {

Просмотреть файл

@ -14,9 +14,12 @@ const TargetBits = 32
//go:extern __heap_base //go:extern __heap_base
var heapStartSymbol unsafe.Pointer var heapStartSymbol unsafe.Pointer
//go:export llvm.wasm.memory.size.i32
func wasm_memory_size(index int32) int32
var ( var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = (heapStart + wasmPageSize - 1) &^ (wasmPageSize - 1) // conservative guess: one page of heap memory heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
) )
const wasmPageSize = 64 * 1024 const wasmPageSize = 64 * 1024