// 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.

// Trace stack table and acquisition.

package runtime

import (
	
	
	
)

// traceTypeTable maps stack traces (arrays of PC's) to unique uint32 ids.
// It is lock-free for reading.
type traceTypeTable struct {
	tab traceMap
}

// put returns a unique id for the type typ and caches it in the table,
// if it's seeing it for the first time.
//
// N.B. typ must be kept alive forever for this to work correctly.
func ( *traceTypeTable) ( *abi.Type) uint64 {
	if  == nil {
		return 0
	}
	// Insert the pointer to the type itself.
	,  := .tab.put(noescape(unsafe.Pointer(&)), goarch.PtrSize)
	return 
}

// dump writes all previously cached types to trace buffers and
// releases all memory and resets state. It must only be called once the caller
// can guarantee that there are no more writers to the table.
func ( *traceTypeTable) ( uintptr) {
	 := unsafeTraceExpWriter(, nil, traceExperimentAllocFree)
	if  := (*traceMapNode)(.tab.root.Load());  != nil {
		 = dumpTypesRec(, )
	}
	.flush().end()
	.tab.reset()
}

func dumpTypesRec( *traceMapNode,  traceWriter) traceWriter {
	 := (*abi.Type)(*(*unsafe.Pointer)(unsafe.Pointer(&.data[0])))
	 := toRType().string()

	// The maximum number of bytes required to hold the encoded type.
	 := 1 + 5*traceBytesPerNumber + len()

	// Estimate the size of this record. This
	// bound is pretty loose, but avoids counting
	// lots of varint sizes.
	//
	// Add 1 because we might also write a traceAllocFreeTypesBatch byte.
	var  bool
	,  = .ensure(1 + )
	if  {
		// Annotate the batch as containing types.
		.byte(byte(traceAllocFreeTypesBatch))
	}

	// Emit type.
	.varint(uint64(.id))
	.varint(uint64(uintptr(unsafe.Pointer())))
	.varint(uint64(.Size()))
	.varint(uint64(.PtrBytes))
	.varint(uint64(len()))
	.stringData()

	// Recursively walk all child nodes.
	for  := range .children {
		 := .children[].Load()
		if  == nil {
			continue
		}
		 = ((*traceMapNode)(), )
	}
	return 
}