// run

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

// TODO: disable test for ppc64le/dynlink? See cmd/compile/internal/reader/noder.go:addTailCall.

package main

import (
	"fmt"
	"runtime"
	"time"
)

type I interface {
	foo() time.Duration // foo returns its running time
}

type base struct {
}

func (b *base) foo() time.Duration {
	t := time.Now()
	var pcs [10]uintptr
	runtime.Callers(1, pcs[:])
	return time.Since(t)
}

type wrap struct {
	I
	data int
}

// best runs f a bunch of times, picks the shortest returned duration.
func best(f func() time.Duration) time.Duration {
	m := f()
	for range 9 {
		m = min(m, f())
	}
	return m
}

func main() {
	if runtime.GOARCH == "wasm" {
		// TODO: upgrade wasm to do indirect tail calls
		return
	}
	var i I = &base{}
	for x := range 1000 {
		i = &wrap{I: i, data: x}
	}
	short := best(i.foo)
	for x := range 9000 {
		i = &wrap{I: i, data: x}
	}
	long := best(i.foo)

	ratio := long.Seconds() / short.Seconds()

	// Running time should be independent of the number of wrappers.
	// Prior to the fix for 75764, it was linear in the number of wrappers.
	// Pre-fix, we get ratios typically in the 7.0-10.0 range.
	// Post-fix, it is in the 1.0-1.5 range.
	allowed := 9.0
	if ratio >= allowed {
		fmt.Printf("short: %v\nlong: %v\nratio: %v\nallowed: %v\n", short, long, ratio, allowed)
	}
}
