Skip to content
Draft
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
8 changes: 3 additions & 5 deletions runtime/abi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ func NoEscape(p unsafe.Pointer) unsafe.Pointer {
return unsafe.Pointer(x ^ 0)
}

type EmptyInterface struct {
Type *Type
Data unsafe.Pointer
}

// TypeOf returns the runtime Type of some value.
func TypeOf(a any) *Type {
eface := *(*EmptyInterface)(unsafe.Pointer(&a))
Expand All @@ -52,3 +47,6 @@ func EscapeToResultNonString[T any](v T) T {
EscapeNonString(v)
return *(*T)(NoEscape(unsafe.Pointer(&v)))
}

// ZeroValSize is the size in bytes of runtime.zeroVal.
const ZeroValSize = 1024
41 changes: 41 additions & 0 deletions runtime/abi/iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package abi

import "unsafe"

// The first word of every non-empty interface type contains an *ITab.
// It records the underlying concrete type (Type), the interface type it
// is implementing (Inter), and some ancillary information.
//
// allocated in non-garbage-collected memory
type ITab struct {
Inter *InterfaceType
Type *Type
Hash uint32 // copy of Type.Hash. Used for type switches.
Fun [1]uintptr // variable sized. fun[0]==0 means Type does not implement Inter.
}

// EmptyInterface describes the layout of a "interface{}" or a "any."
// These are represented differently than non-empty interface, as the first
// word always points to an abi.Type.
type EmptyInterface struct {
Type *Type
Data unsafe.Pointer
}

// NonEmptyInterface describes the layout of an interface that contains any methods.
type NonEmptyInterface struct {
ITab *ITab
Data unsafe.Pointer
}

// CommonInterface describes the layout of both [EmptyInterface] and [NonEmptyInterface].
type CommonInterface struct {
// Either an *ITab or a *Type, unexported to avoid accidental use.
_ unsafe.Pointer

Data unsafe.Pointer
}
33 changes: 33 additions & 0 deletions runtime/abi/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package abi

import "unsafe"

// Map constants common to several packages
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
const (
Expand All @@ -12,3 +14,34 @@ const (
MapMaxKeyBytes = 128 // Must fit in a uint8.
MapMaxElemBytes = 128 // Must fit in a uint8.
)

type MapType struct {
Type
Key *Type
Elem *Type
Bucket *Type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
Hasher func(unsafe.Pointer, uintptr) uintptr
KeySize uint8 // size of key slot
ValueSize uint8 // size of elem slot
BucketSize uint16 // size of bucket
Flags uint32
}

// Note: flag values must match those used in the TMAP case
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
return mt.Flags&1 != 0
}
func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
return mt.Flags&2 != 0
}
func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
return mt.Flags&4 != 0
}
func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
return mt.Flags&8 != 0
}
func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
return mt.Flags&16 != 0
}
64 changes: 64 additions & 0 deletions runtime/abi/map_swiss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package abi

import (
"unsafe"
)

// Map constants common to several packages
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
const (
// Number of bits in the group.slot count.
MapGroupSlotsBits = 3

// Number of slots in a group.
MapGroupSlots = 1 << MapGroupSlotsBits // 8

// Maximum key or elem size to keep inline (instead of mallocing per element).
// Must fit in a uint8.
// MapMaxKeyBytes = 128
// MapMaxElemBytes = 128

ctrlEmpty = 0b10000000
bitsetLSB = 0x0101010101010101

// Value of control word with all empty slots.
MapCtrlEmpty = bitsetLSB * uint64(ctrlEmpty)
)

type SwissMapType struct {
Type
Key *Type
Elem *Type
Group *Type // internal type representing a slot group
// function for hashing keys (ptr to key, seed) -> hash
Hasher func(unsafe.Pointer, uintptr) uintptr
GroupSize uintptr // == Group.Size_
SlotSize uintptr // size of key/elem slot
ElemOff uintptr // offset of elem in key/elem slot
Flags uint32
}

// Flag values
const (
MapNeedKeyUpdate = 1 << iota
MapHashMightPanic
MapIndirectKey
MapIndirectElem
)

func (mt *SwissMapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
return mt.Flags&MapNeedKeyUpdate != 0
}
func (mt *SwissMapType) HashMightPanic() bool { // true if hash function might panic
return mt.Flags&MapHashMightPanic != 0
}
func (mt *SwissMapType) IndirectKey() bool { // store ptr to key instead of key itself
return mt.Flags&MapIndirectKey != 0
}
func (mt *SwissMapType) IndirectElem() bool { // store ptr to elem instead of elem itself
return mt.Flags&MapIndirectElem != 0
}
31 changes: 0 additions & 31 deletions runtime/abi/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,37 +202,6 @@ type SliceType struct {
Elem *Type // slice element type
}

type MapType struct {
Type
Key *Type
Elem *Type
Bucket *Type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
Hasher func(unsafe.Pointer, uintptr) uintptr
KeySize uint8 // size of key slot
ValueSize uint8 // size of elem slot
BucketSize uint16 // size of bucket
Flags uint32
}

// Note: flag values must match those used in the TMAP case
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
return mt.Flags&1 != 0
}
func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
return mt.Flags&2 != 0
}
func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
return mt.Flags&4 != 0
}
func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
return mt.Flags&8 != 0
}
func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
return mt.Flags&16 != 0
}

func (t *Type) Key() *Type {
if t.Kind() == Map {
return (*MapType)(unsafe.Pointer(t)).Key
Expand Down
5 changes: 5 additions & 0 deletions runtime/internal/runtime/goarch/nowasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !wasm

package goarch

const IsWasm = 0
5 changes: 5 additions & 0 deletions runtime/internal/runtime/goarch/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build wasm

package goarch

const IsWasm = 1
Loading
Loading