mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
runtime: add gc layout info for some basic types
This commit is contained in:
@@ -245,6 +245,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||
"internal/cm/": false,
|
||||
"internal/fuzz/": false,
|
||||
"internal/reflectlite/": false,
|
||||
"internal/gclayout": false,
|
||||
"internal/task/": false,
|
||||
"internal/wasi/": false,
|
||||
"machine/": false,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package gclayout
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Internal constants for gc layout
|
||||
// See runtime/gc_precise.go
|
||||
|
||||
var (
|
||||
NoPtrs unsafe.Pointer
|
||||
Pointer unsafe.Pointer
|
||||
String unsafe.Pointer
|
||||
Slice unsafe.Pointer
|
||||
)
|
||||
|
||||
func init() {
|
||||
var sizeBits uintptr
|
||||
|
||||
switch unsafe.Sizeof(uintptr(0)) {
|
||||
case 8:
|
||||
sizeBits = 6
|
||||
case 4:
|
||||
sizeBits = 5
|
||||
case 2:
|
||||
sizeBits = 4
|
||||
}
|
||||
|
||||
var sizeShift = sizeBits + 1
|
||||
|
||||
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
||||
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
||||
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
|
||||
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
|
||||
}
|
||||
@@ -64,6 +64,7 @@
|
||||
package reflect
|
||||
|
||||
import (
|
||||
"internal/gclayout"
|
||||
"internal/itoa"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -961,6 +962,26 @@ func (t *rawType) Align() int {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rawType) gcLayout() unsafe.Pointer {
|
||||
kind := r.Kind()
|
||||
|
||||
if kind < String {
|
||||
return gclayout.NoPtrs
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case Pointer, UnsafePointer, Chan, Map:
|
||||
return gclayout.Pointer
|
||||
case String:
|
||||
return gclayout.String
|
||||
case Slice:
|
||||
return gclayout.Slice
|
||||
}
|
||||
|
||||
// Unknown (for now); let the conservative pointer scanning handle it
|
||||
return nil
|
||||
}
|
||||
|
||||
// FieldAlign returns the alignment if this type is used in a struct field. It
|
||||
// is currently an alias for Align() but this might change in the future.
|
||||
func (t *rawType) FieldAlign() int {
|
||||
|
||||
@@ -1479,7 +1479,8 @@ func MakeSlice(typ Type, len, cap int) Value {
|
||||
ulen := uint(len)
|
||||
ucap := uint(cap)
|
||||
maxSize := (^uintptr(0)) / 2
|
||||
elementSize := rtype.elem().Size()
|
||||
elem := rtype.elem()
|
||||
elementSize := elem.Size()
|
||||
if elementSize > 1 {
|
||||
maxSize /= uintptr(elementSize)
|
||||
}
|
||||
@@ -1493,7 +1494,9 @@ func MakeSlice(typ Type, len, cap int) Value {
|
||||
var slice sliceHeader
|
||||
slice.cap = uintptr(ucap)
|
||||
slice.len = uintptr(ulen)
|
||||
slice.data = alloc(size, nil)
|
||||
layout := elem.gcLayout()
|
||||
|
||||
slice.data = alloc(size, layout)
|
||||
|
||||
return Value{
|
||||
typecode: rtype,
|
||||
|
||||
@@ -3,6 +3,7 @@ package runtime
|
||||
// This file implements compiler builtins for slices: append() and copy().
|
||||
|
||||
import (
|
||||
"internal/gclayout"
|
||||
"math/bits"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -47,7 +48,13 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
|
||||
// memory allocators, this causes some difficult to debug issues.
|
||||
newCap = 1 << bits.Len(uint(newCap))
|
||||
|
||||
buf := alloc(newCap*elemSize, nil)
|
||||
var layout unsafe.Pointer
|
||||
// less type info here; can only go off element size
|
||||
if elemSize < unsafe.Sizeof(uintptr(0)) {
|
||||
layout = gclayout.NoPtrs
|
||||
}
|
||||
|
||||
buf := alloc(newCap*elemSize, layout)
|
||||
if oldLen > 0 {
|
||||
// copy any data to new slice
|
||||
memmove(buf, oldBuf, oldLen*elemSize)
|
||||
|
||||
@@ -3,6 +3,7 @@ package runtime
|
||||
// This file implements functions related to Go strings.
|
||||
|
||||
import (
|
||||
"internal/gclayout"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -59,7 +60,7 @@ func stringConcat(x, y _string) _string {
|
||||
return x
|
||||
} else {
|
||||
length := x.length + y.length
|
||||
buf := alloc(length, nil)
|
||||
buf := alloc(length, gclayout.NoPtrs)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||
memcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length)
|
||||
return _string{ptr: (*byte)(buf), length: length}
|
||||
@@ -72,7 +73,7 @@ func stringFromBytes(x struct {
|
||||
len uintptr
|
||||
cap uintptr
|
||||
}) _string {
|
||||
buf := alloc(x.len, nil)
|
||||
buf := alloc(x.len, gclayout.NoPtrs)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.len)
|
||||
return _string{ptr: (*byte)(buf), length: x.len}
|
||||
}
|
||||
@@ -83,7 +84,7 @@ func stringToBytes(x _string) (slice struct {
|
||||
len uintptr
|
||||
cap uintptr
|
||||
}) {
|
||||
buf := alloc(x.length, nil)
|
||||
buf := alloc(x.length, gclayout.NoPtrs)
|
||||
memcpy(buf, unsafe.Pointer(x.ptr), x.length)
|
||||
slice.ptr = (*byte)(buf)
|
||||
slice.len = x.length
|
||||
@@ -100,7 +101,7 @@ func stringFromRunes(runeSlice []rune) (s _string) {
|
||||
}
|
||||
|
||||
// Allocate memory for the string.
|
||||
s.ptr = (*byte)(alloc(s.length, nil))
|
||||
s.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs))
|
||||
|
||||
// Encode runes to UTF-8 and store the resulting bytes in the string.
|
||||
index := uintptr(0)
|
||||
|
||||
Reference in New Issue
Block a user