mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 10:52:28 -05:00 
			
		
		
		
	[experiment] add alternative wasm sqlite3 implementation available via build-tag (#2863)
This allows for building GoToSocial with [SQLite transpiled to WASM](https://github.com/ncruces/go-sqlite3) and accessed through [Wazero](https://wazero.io/).
This commit is contained in:
		
					parent
					
						
							
								cce21c11cb
							
						
					
				
			
			
				commit
				
					
						1e7b32490d
					
				
			
		
					 398 changed files with 86174 additions and 684 deletions
				
			
		
							
								
								
									
										25
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| package platform | ||||
| 
 | ||||
| // CpuFeatureFlags exposes methods for querying CPU capabilities | ||||
| type CpuFeatureFlags interface { | ||||
| 	// Has returns true when the specified flag (represented as uint64) is supported | ||||
| 	Has(cpuFeature CpuFeature) bool | ||||
| 	// HasExtra returns true when the specified extraFlag (represented as uint64) is supported | ||||
| 	HasExtra(cpuFeature CpuFeature) bool | ||||
| } | ||||
| 
 | ||||
| type CpuFeature uint64 | ||||
| 
 | ||||
| const ( | ||||
| 	// CpuFeatureAmd64SSE3 is the flag to query CpuFeatureFlags.Has for SSEv3 capabilities on amd64 | ||||
| 	CpuFeatureAmd64SSE3 CpuFeature = 1 | ||||
| 	// CpuFeatureAmd64SSE4_1 is the flag to query CpuFeatureFlags.Has for SSEv4.1 capabilities on amd64 | ||||
| 	CpuFeatureAmd64SSE4_1 CpuFeature = 1 << 19 | ||||
| 	// CpuFeatureAmd64SSE4_2 is the flag to query CpuFeatureFlags.Has for SSEv4.2 capabilities on amd64 | ||||
| 	CpuFeatureAmd64SSE4_2 CpuFeature = 1 << 20 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// CpuExtraFeatureAmd64ABM is the flag to query CpuFeatureFlags.HasExtra for Advanced Bit Manipulation capabilities (e.g. LZCNT) on amd64 | ||||
| 	CpuExtraFeatureAmd64ABM CpuFeature = 1 << 5 | ||||
| ) | ||||
							
								
								
									
										59
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| //go:build amd64 && !tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| // CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods | ||||
| var CpuFeatures CpuFeatureFlags = loadCpuFeatureFlags() | ||||
| 
 | ||||
| // cpuFeatureFlags implements CpuFeatureFlags interface | ||||
| type cpuFeatureFlags struct { | ||||
| 	flags      uint64 | ||||
| 	extraFlags uint64 | ||||
| } | ||||
| 
 | ||||
| // cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf) | ||||
| // implemented in impl_amd64.s | ||||
| func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32) | ||||
| 
 | ||||
| // cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap | ||||
| func cpuidAsBitmap(arg1, arg2 uint32) uint64 { | ||||
| 	_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2) | ||||
| 	return (uint64(edx) << 32) | uint64(ecx) | ||||
| } | ||||
| 
 | ||||
| // loadStandardRange load flags from the standard range, panics otherwise | ||||
| func loadStandardRange(id uint32) uint64 { | ||||
| 	// ensure that the id is in the valid range, returned by cpuid(0,0) | ||||
| 	maxRange, _, _, _ := cpuid(0, 0) | ||||
| 	if id > maxRange { | ||||
| 		panic("cannot query standard CPU flags") | ||||
| 	} | ||||
| 	return cpuidAsBitmap(id, 0) | ||||
| } | ||||
| 
 | ||||
| // loadStandardRange load flags from the extended range, panics otherwise | ||||
| func loadExtendedRange(id uint32) uint64 { | ||||
| 	// ensure that the id is in the valid range, returned by cpuid(0x80000000,0) | ||||
| 	maxRange, _, _, _ := cpuid(0x80000000, 0) | ||||
| 	if id > maxRange { | ||||
| 		panic("cannot query extended CPU flags") | ||||
| 	} | ||||
| 	return cpuidAsBitmap(id, 0) | ||||
| } | ||||
| 
 | ||||
| func loadCpuFeatureFlags() CpuFeatureFlags { | ||||
| 	return &cpuFeatureFlags{ | ||||
| 		flags:      loadStandardRange(1), | ||||
| 		extraFlags: loadExtendedRange(0x80000001), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Has implements the same method on the CpuFeatureFlags interface | ||||
| func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { | ||||
| 	return (f.flags & uint64(cpuFeature)) != 0 | ||||
| } | ||||
| 
 | ||||
| // HasExtra implements the same method on the CpuFeatureFlags interface | ||||
| func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { | ||||
| 	return (f.extraFlags & uint64(cpuFeature)) != 0 | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_amd64.s
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| #include "textflag.h" | ||||
| 
 | ||||
| // lifted from github.com/intel-go/cpuid and src/internal/cpu/cpu_x86.s | ||||
| // func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32) | ||||
| TEXT ·cpuid(SB), NOSPLIT, $0-24 | ||||
| 	MOVL arg1+0(FP), AX | ||||
| 	MOVL arg2+4(FP), CX | ||||
| 	CPUID | ||||
| 	MOVL AX, eax+8(FP) | ||||
| 	MOVL BX, ebx+12(FP) | ||||
| 	MOVL CX, ecx+16(FP) | ||||
| 	MOVL DX, edx+20(FP) | ||||
| 	RET | ||||
| 
 | ||||
							
								
								
									
										14
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/cpuid_unsupported.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| //go:build !amd64 || tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| var CpuFeatures CpuFeatureFlags = &cpuFeatureFlags{} | ||||
| 
 | ||||
| // cpuFeatureFlags implements CpuFeatureFlags for unsupported platforms | ||||
| type cpuFeatureFlags struct{} | ||||
| 
 | ||||
| // Has implements the same method on the CpuFeatureFlags interface | ||||
| func (c *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { return false } | ||||
| 
 | ||||
| // HasExtra implements the same method on the CpuFeatureFlags interface | ||||
| func (c *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { return false } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/crypto.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| 	"math/rand" | ||||
| ) | ||||
| 
 | ||||
| // seed is a fixed seed value for NewFakeRandSource. | ||||
| // | ||||
| // Trivia: While arbitrary, 42 was chosen as it is the "Ultimate Answer" in | ||||
| // the Douglas Adams novel "The Hitchhiker's Guide to the Galaxy." | ||||
| const seed = int64(42) | ||||
| 
 | ||||
| // NewFakeRandSource returns a deterministic source of random values. | ||||
| func NewFakeRandSource() io.Reader { | ||||
| 	return rand.New(rand.NewSource(seed)) | ||||
| } | ||||
							
								
								
									
										76
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"math/bits" | ||||
| 	"os" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// https://man7.org/linux/man-pages/man2/mmap.2.html | ||||
| 	__MAP_HUGE_SHIFT = 26 | ||||
| 	__MAP_HUGETLB    = 0x40000 | ||||
| ) | ||||
| 
 | ||||
| var hugePagesConfigs []hugePagesConfig | ||||
| 
 | ||||
| type hugePagesConfig struct { | ||||
| 	size int | ||||
| 	flag int | ||||
| } | ||||
| 
 | ||||
| func (hpc *hugePagesConfig) match(size int) bool { | ||||
| 	return (size & (hpc.size - 1)) == 0 | ||||
| } | ||||
| 
 | ||||
| func init() { | ||||
| 	dirents, err := os.ReadDir("/sys/kernel/mm/hugepages/") | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for _, dirent := range dirents { | ||||
| 		name := dirent.Name() | ||||
| 		if !strings.HasPrefix(name, "hugepages-") { | ||||
| 			continue | ||||
| 		} | ||||
| 		if !strings.HasSuffix(name, "kB") { | ||||
| 			continue | ||||
| 		} | ||||
| 		n, err := strconv.ParseUint(name[10:len(name)-2], 10, 64) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		if bits.OnesCount64(n) != 1 { | ||||
| 			continue | ||||
| 		} | ||||
| 		n *= 1024 | ||||
| 		hugePagesConfigs = append(hugePagesConfigs, hugePagesConfig{ | ||||
| 			size: int(n), | ||||
| 			flag: int(bits.TrailingZeros64(n)<<__MAP_HUGE_SHIFT) | __MAP_HUGETLB, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	sort.Slice(hugePagesConfigs, func(i, j int) bool { | ||||
| 		return hugePagesConfigs[i].size > hugePagesConfigs[j].size | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func mmapCodeSegment(size, prot int) ([]byte, error) { | ||||
| 	flags := syscall.MAP_ANON | syscall.MAP_PRIVATE | ||||
| 
 | ||||
| 	for _, hugePagesConfig := range hugePagesConfigs { | ||||
| 		if hugePagesConfig.match(size) { | ||||
| 			b, err := syscall.Mmap(-1, 0, size, prot, flags|hugePagesConfig.flag) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			return b, nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return syscall.Mmap(-1, 0, size, prot, flags) | ||||
| } | ||||
							
								
								
									
										18
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_other.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| // Separated from linux which has support for huge pages. | ||||
| //go:build darwin || freebsd | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| import "syscall" | ||||
| 
 | ||||
| func mmapCodeSegment(size, prot int) ([]byte, error) { | ||||
| 	return syscall.Mmap( | ||||
| 		-1, | ||||
| 		0, | ||||
| 		size, | ||||
| 		prot, | ||||
| 		// Anonymous as this is not an actual file, but a memory, | ||||
| 		// Private as this is in-process memory region. | ||||
| 		syscall.MAP_ANON|syscall.MAP_PRIVATE, | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										49
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| //go:build (darwin || linux || freebsd) && !tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	mmapProtAMD64 = syscall.PROT_READ | syscall.PROT_WRITE | syscall.PROT_EXEC | ||||
| 	mmapProtARM64 = syscall.PROT_READ | syscall.PROT_WRITE | ||||
| ) | ||||
| 
 | ||||
| const MmapSupported = true | ||||
| 
 | ||||
| func munmapCodeSegment(code []byte) error { | ||||
| 	return syscall.Munmap(code) | ||||
| } | ||||
| 
 | ||||
| // mmapCodeSegmentAMD64 gives all read-write-exec permission to the mmap region | ||||
| // to enter the function. Otherwise, segmentation fault exception is raised. | ||||
| func mmapCodeSegmentAMD64(size int) ([]byte, error) { | ||||
| 	// The region must be RWX: RW for writing native codes, X for executing the region. | ||||
| 	return mmapCodeSegment(size, mmapProtAMD64) | ||||
| } | ||||
| 
 | ||||
| // mmapCodeSegmentARM64 cannot give all read-write-exec permission to the mmap region. | ||||
| // Otherwise, the mmap systemcall would raise an error. Here we give read-write | ||||
| // to the region so that we can write contents at call-sites. Callers are responsible to | ||||
| // execute MprotectRX on the returned buffer. | ||||
| func mmapCodeSegmentARM64(size int) ([]byte, error) { | ||||
| 	// The region must be RW: RW for writing native codes. | ||||
| 	return mmapCodeSegment(size, mmapProtARM64) | ||||
| } | ||||
| 
 | ||||
| // MprotectRX is like syscall.Mprotect with RX permission, defined locally so that freebsd compiles. | ||||
| func MprotectRX(b []byte) (err error) { | ||||
| 	var _p0 unsafe.Pointer | ||||
| 	if len(b) > 0 { | ||||
| 		_p0 = unsafe.Pointer(&b[0]) | ||||
| 	} | ||||
| 	const prot = syscall.PROT_READ | syscall.PROT_EXEC | ||||
| 	_, _, e1 := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) | ||||
| 	if e1 != 0 { | ||||
| 		err = syscall.Errno(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										28
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_unsupported.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| //go:build !(darwin || linux || freebsd || windows) || tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"runtime" | ||||
| ) | ||||
| 
 | ||||
| var errUnsupported = fmt.Errorf("mmap unsupported on GOOS=%s. Use interpreter instead.", runtime.GOOS) | ||||
| 
 | ||||
| const MmapSupported = false | ||||
| 
 | ||||
| func munmapCodeSegment(code []byte) error { | ||||
| 	panic(errUnsupported) | ||||
| } | ||||
| 
 | ||||
| func mmapCodeSegmentAMD64(size int) ([]byte, error) { | ||||
| 	panic(errUnsupported) | ||||
| } | ||||
| 
 | ||||
| func mmapCodeSegmentARM64(size int) ([]byte, error) { | ||||
| 	panic(errUnsupported) | ||||
| } | ||||
| 
 | ||||
| func MprotectRX(b []byte) (err error) { | ||||
| 	panic(errUnsupported) | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mmap_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | |||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	kernel32           = syscall.NewLazyDLL("kernel32.dll") | ||||
| 	procVirtualAlloc   = kernel32.NewProc("VirtualAlloc") | ||||
| 	procVirtualProtect = kernel32.NewProc("VirtualProtect") | ||||
| 	procVirtualFree    = kernel32.NewProc("VirtualFree") | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	windows_MEM_COMMIT             uintptr = 0x00001000 | ||||
| 	windows_MEM_RELEASE            uintptr = 0x00008000 | ||||
| 	windows_PAGE_READWRITE         uintptr = 0x00000004 | ||||
| 	windows_PAGE_EXECUTE_READ      uintptr = 0x00000020 | ||||
| 	windows_PAGE_EXECUTE_READWRITE uintptr = 0x00000040 | ||||
| ) | ||||
| 
 | ||||
| const MmapSupported = true | ||||
| 
 | ||||
| func munmapCodeSegment(code []byte) error { | ||||
| 	return freeMemory(code) | ||||
| } | ||||
| 
 | ||||
| // allocateMemory commits the memory region via the "VirtualAlloc" function. | ||||
| // See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc | ||||
| func allocateMemory(size uintptr, protect uintptr) (uintptr, error) { | ||||
| 	address := uintptr(0) // system determines where to allocate the region. | ||||
| 	alloctype := windows_MEM_COMMIT | ||||
| 	if r, _, err := procVirtualAlloc.Call(address, size, alloctype, protect); r == 0 { | ||||
| 		return 0, fmt.Errorf("compiler: VirtualAlloc error: %w", ensureErr(err)) | ||||
| 	} else { | ||||
| 		return r, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // freeMemory releases the memory region via the "VirtualFree" function. | ||||
| // See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualfree | ||||
| func freeMemory(code []byte) error { | ||||
| 	address := unsafe.Pointer(&code[0]) | ||||
| 	size := uintptr(0) // size must be 0 because we're using MEM_RELEASE. | ||||
| 	freetype := windows_MEM_RELEASE | ||||
| 	if r, _, err := procVirtualFree.Call(uintptr(address), size, freetype); r == 0 { | ||||
| 		return fmt.Errorf("compiler: VirtualFree error: %w", ensureErr(err)) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func virtualProtect(address, size, newprotect uintptr, oldprotect *uint32) error { | ||||
| 	if r, _, err := procVirtualProtect.Call(address, size, newprotect, uintptr(unsafe.Pointer(oldprotect))); r == 0 { | ||||
| 		return fmt.Errorf("compiler: VirtualProtect error: %w", ensureErr(err)) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func mmapCodeSegmentAMD64(size int) ([]byte, error) { | ||||
| 	p, err := allocateMemory(uintptr(size), windows_PAGE_EXECUTE_READWRITE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return unsafe.Slice((*byte)(unsafe.Pointer(p)), size), nil | ||||
| } | ||||
| 
 | ||||
| func mmapCodeSegmentARM64(size int) ([]byte, error) { | ||||
| 	p, err := allocateMemory(uintptr(size), windows_PAGE_READWRITE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return unsafe.Slice((*byte)(unsafe.Pointer(p)), size), nil | ||||
| } | ||||
| 
 | ||||
| var old = uint32(windows_PAGE_READWRITE) | ||||
| 
 | ||||
| func MprotectRX(b []byte) (err error) { | ||||
| 	err = virtualProtect(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), windows_PAGE_EXECUTE_READ, &old) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // ensureErr returns syscall.EINVAL when the input error is nil. | ||||
| // | ||||
| // We are supposed to use "GetLastError" which is more precise, but it is not safe to execute in goroutines. While | ||||
| // "GetLastError" is thread-local, goroutines are not pinned to threads. | ||||
| // | ||||
| // See https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror | ||||
| func ensureErr(err error) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return syscall.EINVAL | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mremap_other.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mremap_other.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| //go:build !(darwin || linux || freebsd) || tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| func remapCodeSegmentAMD64(code []byte, size int) ([]byte, error) { | ||||
| 	b, err := mmapCodeSegmentAMD64(size) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	copy(b, code) | ||||
| 	mustMunmapCodeSegment(code) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func remapCodeSegmentARM64(code []byte, size int) ([]byte, error) { | ||||
| 	b, err := mmapCodeSegmentARM64(size) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	copy(b, code) | ||||
| 	mustMunmapCodeSegment(code) | ||||
| 	return b, nil | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mremap_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/mremap_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| //go:build (darwin || linux || freebsd) && !tinygo | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| func remapCodeSegmentAMD64(code []byte, size int) ([]byte, error) { | ||||
| 	return remapCodeSegment(code, size, mmapProtAMD64) | ||||
| } | ||||
| 
 | ||||
| func remapCodeSegmentARM64(code []byte, size int) ([]byte, error) { | ||||
| 	return remapCodeSegment(code, size, mmapProtARM64) | ||||
| } | ||||
| 
 | ||||
| func remapCodeSegment(code []byte, size, prot int) ([]byte, error) { | ||||
| 	b, err := mmapCodeSegment(size, prot) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	copy(b, code) | ||||
| 	mustMunmapCodeSegment(code) | ||||
| 	return b, nil | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/path.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/path.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| //go:build !windows | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| // ToPosixPath returns the input, as only windows might return backslashes. | ||||
| func ToPosixPath(in string) string { return in } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/path_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| package platform | ||||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| // ToPosixPath returns the input, converting any backslashes to forward ones. | ||||
| func ToPosixPath(in string) string { | ||||
| 	// strings.Map only allocates on change, which is good enough especially as | ||||
| 	// path.Join uses forward slash even on windows. | ||||
| 	return strings.Map(windowsToPosixSeparator, in) | ||||
| } | ||||
| 
 | ||||
| func windowsToPosixSeparator(r rune) rune { | ||||
| 	if r == '\\' { | ||||
| 		return '/' | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
							
								
								
									
										81
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| // Package platform includes runtime-specific code needed for the compiler or otherwise. | ||||
| // | ||||
| // Note: This is a dependency-free alternative to depending on parts of Go's x/sys. | ||||
| // See /RATIONALE.md for more context. | ||||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| ) | ||||
| 
 | ||||
| // archRequirementsVerified is set by platform-specific init to true if the platform is supported | ||||
| var archRequirementsVerified bool | ||||
| 
 | ||||
| // CompilerSupported is exported for tests and includes constraints here and also the assembler. | ||||
| func CompilerSupported() bool { | ||||
| 	switch runtime.GOOS { | ||||
| 	case "darwin", "windows", "linux", "freebsd": | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	return archRequirementsVerified | ||||
| } | ||||
| 
 | ||||
| // MmapCodeSegment copies the code into the executable region and returns the byte slice of the region. | ||||
| // | ||||
| // See https://man7.org/linux/man-pages/man2/mmap.2.html for mmap API and flags. | ||||
| func MmapCodeSegment(size int) ([]byte, error) { | ||||
| 	if size == 0 { | ||||
| 		panic("BUG: MmapCodeSegment with zero length") | ||||
| 	} | ||||
| 	if runtime.GOARCH == "amd64" { | ||||
| 		return mmapCodeSegmentAMD64(size) | ||||
| 	} else { | ||||
| 		return mmapCodeSegmentARM64(size) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RemapCodeSegment reallocates the memory mapping of an existing code segment | ||||
| // to increase its size. The previous code mapping is unmapped and must not be | ||||
| // reused after the function returns. | ||||
| // | ||||
| // This is similar to mremap(2) on linux, and emulated on platforms which do not | ||||
| // have this syscall. | ||||
| // | ||||
| // See https://man7.org/linux/man-pages/man2/mremap.2.html | ||||
| func RemapCodeSegment(code []byte, size int) ([]byte, error) { | ||||
| 	if size < len(code) { | ||||
| 		panic("BUG: RemapCodeSegment with size less than code") | ||||
| 	} | ||||
| 	if code == nil { | ||||
| 		return MmapCodeSegment(size) | ||||
| 	} | ||||
| 	if runtime.GOARCH == "amd64" { | ||||
| 		return remapCodeSegmentAMD64(code, size) | ||||
| 	} else { | ||||
| 		return remapCodeSegmentARM64(code, size) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // MunmapCodeSegment unmaps the given memory region. | ||||
| func MunmapCodeSegment(code []byte) error { | ||||
| 	if len(code) == 0 { | ||||
| 		panic("BUG: MunmapCodeSegment with zero length") | ||||
| 	} | ||||
| 	return munmapCodeSegment(code) | ||||
| } | ||||
| 
 | ||||
| // mustMunmapCodeSegment panics instead of returning an error to the | ||||
| // application. | ||||
| // | ||||
| // # Why panic? | ||||
| // | ||||
| // It is less disruptive to the application to leak the previous block if it | ||||
| // could be unmapped than to leak the new block and return an error. | ||||
| // Realistically, either scenarios are pretty hard to debug, so we panic. | ||||
| func mustMunmapCodeSegment(code []byte) { | ||||
| 	if err := munmapCodeSegment(code); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform_amd64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform_amd64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| package platform | ||||
| 
 | ||||
| // init verifies that the current CPU supports the required AMD64 instructions | ||||
| func init() { | ||||
| 	// Ensure SSE4.1 is supported. | ||||
| 	archRequirementsVerified = CpuFeatures.Has(CpuFeatureAmd64SSE4_1) | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform_arm64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/platform_arm64.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| package platform | ||||
| 
 | ||||
| // init verifies that the current CPU supports the required ARM64 features | ||||
| func init() { | ||||
| 	// No further checks currently needed. | ||||
| 	archRequirementsVerified = true | ||||
| } | ||||
							
								
								
									
										76
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/tetratelabs/wazero/sys" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	ms = int64(time.Millisecond) | ||||
| 	// FakeEpochNanos is midnight UTC 2022-01-01 and exposed for testing | ||||
| 	FakeEpochNanos = 1640995200000 * ms | ||||
| ) | ||||
| 
 | ||||
| // NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading. | ||||
| // See /RATIONALE.md | ||||
| func NewFakeWalltime() sys.Walltime { | ||||
| 	// AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos | ||||
| 	t := FakeEpochNanos - ms | ||||
| 	return func() (sec int64, nsec int32) { | ||||
| 		wt := atomic.AddInt64(&t, ms) | ||||
| 		return wt / 1e9, int32(wt % 1e9) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading. | ||||
| // See /RATIONALE.md | ||||
| func NewFakeNanotime() sys.Nanotime { | ||||
| 	// AddInt64 returns the new value. Adjust so the first reading will be zero. | ||||
| 	t := int64(0) - ms | ||||
| 	return func() int64 { | ||||
| 		return atomic.AddInt64(&t, ms) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // FakeNanosleep implements sys.Nanosleep by returning without sleeping. | ||||
| var FakeNanosleep = sys.Nanosleep(func(int64) {}) | ||||
| 
 | ||||
| // FakeOsyield implements sys.Osyield by returning without yielding. | ||||
| var FakeOsyield = sys.Osyield(func() {}) | ||||
| 
 | ||||
| // Walltime implements sys.Walltime with time.Now. | ||||
| // | ||||
| // Note: This is only notably less efficient than it could be is reading | ||||
| // runtime.walltime(). time.Now defensively reads nanotime also, just in case | ||||
| // time.Since is used. This doubles the performance impact. However, wall time | ||||
| // is likely to be read less frequently than Nanotime. Also, doubling the cost | ||||
| // matters less on fast platforms that can return both in <=100ns. | ||||
| func Walltime() (sec int64, nsec int32) { | ||||
| 	t := time.Now() | ||||
| 	return t.Unix(), int32(t.Nanosecond()) | ||||
| } | ||||
| 
 | ||||
| // nanoBase uses time.Now to ensure a monotonic clock reading on all platforms | ||||
| // via time.Since. | ||||
| var nanoBase = time.Now() | ||||
| 
 | ||||
| // nanotimePortable implements sys.Nanotime with time.Since. | ||||
| // | ||||
| // Note: This is less efficient than it could be is reading runtime.nanotime(), | ||||
| // Just to do that requires CGO. | ||||
| func nanotimePortable() int64 { | ||||
| 	return time.Since(nanoBase).Nanoseconds() | ||||
| } | ||||
| 
 | ||||
| // Nanotime implements sys.Nanotime with runtime.nanotime() if CGO is available | ||||
| // and time.Since if not. | ||||
| func Nanotime() int64 { | ||||
| 	return nanotime() | ||||
| } | ||||
| 
 | ||||
| // Nanosleep implements sys.Nanosleep with time.Sleep. | ||||
| func Nanosleep(ns int64) { | ||||
| 	time.Sleep(time.Duration(ns)) | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_cgo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| //go:build cgo && !windows | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| import _ "unsafe" // for go:linkname | ||||
| 
 | ||||
| // nanotime uses runtime.nanotime as it is available on all platforms and | ||||
| // benchmarks faster than using time.Since. | ||||
| // | ||||
| //go:linkname nanotime runtime.nanotime | ||||
| func nanotime() int64 | ||||
							
								
								
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_notcgo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| //go:build !cgo && !windows | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| func nanotime() int64 { | ||||
| 	return nanotimePortable() | ||||
| } | ||||
							
								
								
									
										40
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/tetratelabs/wazero/internal/platform/time_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| //go:build windows | ||||
| 
 | ||||
| package platform | ||||
| 
 | ||||
| import ( | ||||
| 	"math/bits" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	_QueryPerformanceCounter   = kernel32.NewProc("QueryPerformanceCounter") | ||||
| 	_QueryPerformanceFrequency = kernel32.NewProc("QueryPerformanceFrequency") | ||||
| ) | ||||
| 
 | ||||
| var qpcfreq uint64 | ||||
| 
 | ||||
| func init() { | ||||
| 	_, _, _ = _QueryPerformanceFrequency.Call(uintptr(unsafe.Pointer(&qpcfreq))) | ||||
| } | ||||
| 
 | ||||
| // On Windows, time.Time handled in time package cannot have the nanosecond precision. | ||||
| // The reason is that by default, it doesn't use QueryPerformanceCounter[1], but instead, use "interrupt time" | ||||
| // which doesn't support nanoseconds precision (though it is a monotonic) [2, 3, 4, 5]. | ||||
| // | ||||
| // [1] https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter | ||||
| // [2] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/sys_windows_amd64.s#L297-L298 | ||||
| // [3] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/os_windows.go#L549-L551 | ||||
| // [4] https://github.com/golang/go/blob/master/src/runtime/time_windows.h#L7-L13 | ||||
| // [5] http://web.archive.org/web/20210411000829/https://wrkhpi.wordpress.com/2007/08/09/getting-os-information-the-kuser_shared_data-structure/ | ||||
| // | ||||
| // Therefore, on Windows, we directly invoke the syscall for QPC instead of time.Now or runtime.nanotime. | ||||
| // See https://github.com/golang/go/issues/31160 for example. | ||||
| func nanotime() int64 { | ||||
| 	var counter uint64 | ||||
| 	_, _, _ = _QueryPerformanceCounter.Call(uintptr(unsafe.Pointer(&counter))) | ||||
| 	hi, lo := bits.Mul64(counter, uint64(time.Second)) | ||||
| 	nanos, _ := bits.Div64(hi, lo, qpcfreq) | ||||
| 	return int64(nanos) | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue