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
tags string
wasmAbi string
heapSize int64
testConfig compiler.TestConfig
}
@ -240,10 +241,16 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
// Prepare link command.
executable := filepath.Join(dir, "main")
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" {
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.
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() {
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
fmt.Fprintln(os.Stderr, "version:", version)
@ -598,6 +629,7 @@ func main() {
cFlags := flag.String("cflags", "", "additional cflags for compiler")
ldFlags := flag.String("ldflags", "", "additional ldflags for linker")
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 {
fmt.Fprintln(os.Stderr, "No command-line arguments supplied.")
@ -633,6 +665,13 @@ func main() {
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)
switch command {

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

@ -14,9 +14,12 @@ const TargetBits = 32
//go:extern __heap_base
var heapStartSymbol unsafe.Pointer
//go:export llvm.wasm.memory.size.i32
func wasm_memory_size(index int32) int32
var (
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