Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compileopts/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@ func (c *Config) LDFlags() []string {
if c.Target.LinkerScript != "" {
ldflags = append(ldflags, "-T", c.Target.LinkerScript)
}
if c.Target.Linker == "wasm-ld" && c.Scheduler() == "none" && c.Options.StackSize != 0 {
ldflags = append(ldflags, "-z", fmt.Sprintf("stack-size=%d", c.Options.StackSize))
}
ldflags = append(ldflags, c.Options.ExtLDFlags...)

return ldflags
Expand Down
17 changes: 17 additions & 0 deletions src/internal/poll/fd_wasip1.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,10 @@ const (
// package syscall (intentionally duplicated rather than linknamed
// across the package boundary — see project memory on shim avoidance).
func wait(fd int, mode uint8) {
if task.OnSystemStack() {
task.Pause()
return
}
pd := runtime_netpoll_addwait(uint32(fd), mode)
task.Pause()
runtime_netpoll_done(pd)
Expand All @@ -538,6 +542,10 @@ func (fd *FD) parkUntil(mode uint8, deadline time.Time) error {
if d <= 0 {
return ErrDeadlineExceeded
}
if task.OnSystemStack() {
task.Pause()
return nil
}
pd := runtime_netpoll_addwait(uint32(fd.Sysfd), mode)
timer := time.AfterFunc(d, func() {
runtime_netpoll_wake(pd)
Expand All @@ -548,6 +556,15 @@ func (fd *FD) parkUntil(mode uint8, deadline time.Time) error {
return nil
}

// WaitWrite waits until data can be written to fd.
func (fd *FD) WaitWrite() error {
if fd.wDeadline.IsZero() {
wait(fd.Sysfd, pollModeWrite)
return nil
}
return fd.parkUntil(pollModeWrite, fd.wDeadline)
}

// byteCount turns the -1 a failed read or write returns into 0, as Go's
// internal/poll does in fd_unix.go.
func byteCount(n int, err error) (int, error) {
Expand Down
21 changes: 11 additions & 10 deletions src/runtime/arch_tinygowasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,17 @@ func saveStackPointer() {
// growHeap tries to grow the heap size. It returns true if it succeeds, false
// otherwise.
func growHeap() bool {
// Grow memory by the available size, which means the heap size is doubled.
// Grow memory by up to 64 MiB at a time and back off if the host caps memory.
// Cap total pages at 65535 so uintptr(pages) * wasmPageSize does not wrap to 0.
const maxPages = 65535
memorySize := wasm_memory_size(wasmMemoryIndex)
result := wasm_memory_grow(wasmMemoryIndex, memorySize)
if result == -1 {
// Grow failed.
return false
growPages := min(memorySize, 1024, maxPages-memorySize)
for growPages > 0 {
if wasm_memory_grow(wasmMemoryIndex, growPages) != -1 {
setHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex)) * wasmPageSize)
return true
}
growPages /= 2
}

setHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize))

// Heap has grown successfully.
return true
return false
}
24 changes: 14 additions & 10 deletions src/runtime/hashmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, typeInfo unsafe.P
// it. This is used for the clear builtin, and can be used to reuse a map (to
// avoid extra heap allocations).
func hashmapClear(m *hashmap) {
if m == nil {
if m == nil || m.count == 0 {
// Nothing to do. According to the spec:
// > If the map or slice is nil, clear is a no-op.
return
Expand Down Expand Up @@ -415,15 +415,19 @@ func hashmapCopy(m *hashmap, sizeBits uint8) hashmap {
bucketBufSize := hashmapBucketSize(m)
n.buckets = alloc(bucketBufSize*numBuckets, hashmapType(m).bucketLayout)

// use a hashmap iterator to go through the old map
var it hashmapIterator

var key = alloc(m.keySize, hashmapType(m).keyLayout)
var value = alloc(m.valueSize, hashmapType(m).valueLayout)

for hashmapNext(m, &it, key, value) {
h := n.keyHash(key, uintptr(n.keySize), n.seed)
hashmapSet(&n, key, value, h)
oldNumBuckets := uintptr(1) << m.bucketBits
for i := uintptr(0); i < oldNumBuckets; i++ {
for b := hashmapBucketAddr(m, m.buckets, i); b != nil; b = b.next {
for j := uint8(0); j < 8; j++ {
if b.tophash[j] == 0 {
continue
}
key := hashmapSlotKeyData(m, hashmapSlotKey(m, b, j))
value := hashmapSlotValueData(m, hashmapSlotValue(m, b, j))
h := n.keyHash(key, uintptr(n.keySize), n.seed)
hashmapSet(&n, key, value, h)
}
}
}

return n
Expand Down
20 changes: 14 additions & 6 deletions src/runtime/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,20 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr,
// No need to grow, return the input slice.
return oldBuf, oldLen, oldCap
}

// This can be made more memory-efficient by multiplying by some other constant, such as 1.5,
// which seems to be allowed by the Go language specification (but this can be observed by
// programs); however, due to memory fragmentation and the current state of the TinyGo
// memory allocators, this causes some difficult to debug issues.
newCap = 1 << bits.Len(uint(newCap))
if elemSize == 0 {
return oldBuf, oldLen, newCap
}
if oldCap < 256 {
newCap = 1 << bits.Len(uint(newCap))
} else {
growCap := oldCap
for 0 < growCap && growCap < newCap {
growCap += (growCap + 3*256) / 4
}
if growCap > 0 {
newCap = growCap
}
}

buf := alloc(newCap*elemSize, layout)
if oldLen > 0 {
Expand Down