Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/staticinit/sched.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ func (s *Schedule) initplan(n ir.Node) {
if a.Sym().IsBlank() {
continue
}
s.addvalue(p, a.Field.Offset, a.Value)
s.addvalue(p, typecheck.FieldOffset(n.Type(), a.Field), a.Value)
}

case ir.OMAPLIT:
Expand Down
18 changes: 18 additions & 0 deletions src/cmd/compile/internal/typecheck/subr.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,3 +790,21 @@ var slist []symlink
type symlink struct {
field *types.Field
}

// FieldOffset returns the offset of field f in t,
// including any implicit offsets from embedded fields.
func FieldOffset(t *types.Type, f *types.Field) int64 {
if f.Sym == nil {
return f.Offset
}
path, ambig := dotpath(f.Sym, t, nil, false)
if path == nil || ambig {
return f.Offset
}
var offset int64
for _, d := range path {
offset += d.field.Offset
}
offset += f.Offset
return offset
}
60 changes: 60 additions & 0 deletions src/crypto/internal/cryptotest/wycheproof/_schema/schema_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
package main

import (
"bufio"
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"strings"

"github.com/atombender/go-jsonschema/pkg/generator"
"github.com/c2sp/wycheproof"
Expand Down Expand Up @@ -88,4 +91,61 @@ func main() {
if err := os.WriteFile(outFile, content, 0644); err != nil {
log.Fatalf("error writing file %s: %v\n", outFile, err)
}

// Write a sibling file recording the Wycheproof module version that the
// generated schema.go was produced against. The wycheproof package uses
// this constant to fetch matching test vectors at runtime. We avoid reading
// go.sum at test time because it might not be available (e.g. if the test
// binary was copied to a remote machine).
version, err := wycheproofVersionFromSum("go.sum")
if err != nil {
log.Fatalf("extracting wycheproof version: %v", err)
}
const versionFile = "../schemaversion.go"
versionSrc := fmt.Sprintf(`// 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.

// Code generated by _schema/schema_gen.go, DO NOT EDIT.

package wycheproof

// wycheproofVersion is the github.com/c2sp/wycheproof module version that
// schema.go was generated against.
const wycheproofVersion = %q
`, version)
if err := os.WriteFile(versionFile, []byte(versionSrc), 0644); err != nil {
log.Fatalf("writing %s: %v", versionFile, err)
}
}

// wycheproofVersionFromSum returns the github.com/c2sp/wycheproof module
// version recorded in the given go.sum file.
func wycheproofVersionFromSum(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()

var version string
found := 0
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) == 3 && fields[0] == "github.com/c2sp/wycheproof" {
version = strings.TrimSuffix(fields[1], "/go.mod")
found++
}
}
if err := scanner.Err(); err != nil {
return "", err
}
switch {
case found == 0:
return "", fmt.Errorf("%s: missing github.com/c2sp/wycheproof entry", path)
case found > 2:
return "", fmt.Errorf("%s: %d github.com/c2sp/wycheproof entries (run 'go mod tidy')", path, found)
}
return version, nil
}
11 changes: 11 additions & 0 deletions src/crypto/internal/cryptotest/wycheproof/schemaversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 4 additions & 42 deletions src/crypto/internal/cryptotest/wycheproof/wycheproof.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package wycheproof

import (
"bufio"
"crypto"
"crypto/internal/cryptotest"
"encoding/hex"
Expand All @@ -18,7 +17,6 @@ import (
"os"
"path"
"reflect"
"strings"
"testing"
)

Expand All @@ -34,9 +32,11 @@ func LoadVectorFile(t *testing.T, filename string, value any) {

// We want to avoid a dependency on c2sp/wycheproof or the schema generator
// in this stdlib code, so we fetch the module at runtime and read the
// vector JSON from that module clone.
// vector JSON from that module clone. The version is pinned to whatever
// the _schema generator was last run against (see schemaversion.go), so
// the vectors match the generated schema.go.
wycheproofDir := cryptotest.FetchModule(
t, "github.com/c2sp/wycheproof", findVersionFromSum(t))
t, "github.com/c2sp/wycheproof", wycheproofVersion)

content, err := os.ReadFile(path.Join(wycheproofDir, "testvectors_v1", filename))
if err != nil {
Expand All @@ -49,44 +49,6 @@ func LoadVectorFile(t *testing.T, filename string, value any) {
}
}

// To make sure this code fetches the same module version as we used to
// generate the vendored schema.go we parse the _schema Go module's
// go.sum to find the Wycheproof version used.
func findVersionFromSum(t *testing.T) string {
testenv.MustHaveSource(t)

goSumPath := path.Join(
testenv.GOROOT(t),
"src/crypto/internal/cryptotest/wycheproof/_schema/go.sum")
f, err := os.Open(goSumPath)
if err != nil {
t.Fatalf("_schema module go.sum read failed: %v", err)
}
defer f.Close()

var version string
found := 0
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) == 3 && fields[0] == "github.com/c2sp/wycheproof" {
version = strings.TrimSuffix(fields[1], "/go.mod")
found++
}
}

// We expect 2 entries for a tidied sum file.
if found > 2 {
t.Fatalf(
"_schema module requires 'go tidy' - found %d wycheproof occurrences in go.sum",
found)
} else if found == 0 {
t.Fatal("_schema module go.sum missing wycheproof dependency")
}

return version
}

// ShouldPass returns true if a test should pass informed by expected result
// and flags.
//
Expand Down
36 changes: 22 additions & 14 deletions src/runtime/malloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1076,17 +1076,29 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
return unsafe.Pointer(&zerobase)
}

if sizeSpecializedMallocEnabled && size < uintptr(len(mallocNoScanTable)) {
if typ == nil || !typ.Pointers() {
if size >= maxTinySize {
return mallocNoScanTable[size](size, typ, needzero)
if sizeSpecializedMallocEnabled {
if size < uintptr(len(mallocNoScanTable)) {
if typ == nil || !typ.Pointers() {
if size >= maxTinySize {
return mallocNoScanTable[size](size, typ, needzero)
}
return mallocgcTinySC2(size, typ, needzero)
} else {
if !needzero {
throw("objects with pointers must be zeroed")
}
return mallocScanTable[size](size, typ, needzero)
}
return mallocgcTinySC2(size, typ, needzero)
} else {
if !needzero {
throw("objects with pointers must be zeroed")
}
if heapBitsInSpan(size) {
noscan := typ == nil || !typ.Pointers()
sc := gc.SizeToSizeClass8[divRoundUp(size, gc.SmallSizeDiv)]
elemsize := uintptr(gc.SizeClassToSize[sc])
spc := makeSpanClass(sc, noscan)
if noscan {
return mallocgcSmallNoScanSlowPath(size, typ, needzero, spc, elemsize)
}
return mallocScanTable[size](size, typ, needzero)
return mallocgcSmallScanSlowPath(size, typ, needzero, spc, elemsize)
}
}

Expand Down Expand Up @@ -1127,11 +1139,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
if !needzero {
throw("objects with pointers must be zeroed")
}
if heapBitsInSpan(size) {
x, elemsize = mallocgcSmallScanNoHeader(size, typ)
} else {
x, elemsize = mallocgcSmallScanHeader(size, typ)
}
x, elemsize = mallocgcSmallScanHeader(size, typ)
}
} else {
x, elemsize = mallocgcLarge(size, typ, needzero)
Expand Down
3 changes: 0 additions & 3 deletions src/runtime/trace/subscribe.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,3 @@ func (t *traceMultiplexer) startLocked() error {
t.enabled.Store(true)
return nil
}

//go:linkname runtime_readTrace
func runtime_readTrace() (buf []byte)
4 changes: 4 additions & 0 deletions test/complit2.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ type C struct {
func main() {
eq(A{1, B{b: "foo"}}, A{a: 1, b: "foo"})
eq(A{B: B{C: C{c: "foo"}}}, A{c: "foo"})
eq(x, A{B: B{b: "foo"}})
}

func eq(x, y any) {
if x != y {
panic(fmt.Sprintf("%v != %v", x, y))
}
}

// test global initializer
var x = A{b: "foo"}
6 changes: 3 additions & 3 deletions test/fixedbugs/issue18149.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

// Since go.dev/issue/70478, the compiler resolves a relative filename in a
// //line directive against the directory of the source file, so the expected
// line directive against the directory of the source file, so the expected
// path may be a suffix of the actual filename rather than equal to it.
// Accept either an exact match or the file as a path-component suffix.
// Compiler-emitted paths are always slash-normalized (cmd/internal/objabi.AbsFile).
Expand All @@ -36,7 +36,7 @@ func check(file string, line int) {

func main() {
//line /foo/bar.go:123
check(`/foo/bar.go`, 123)
check("/foo/bar.go", 123)
//line c:/foo/bar.go:987
check(`c:/foo/bar.go`, 987)
check("c:/foo/bar.go", 987)
}
27 changes: 13 additions & 14 deletions test/fixedbugs/issue22660.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
Expand All @@ -20,33 +19,33 @@ import (
)

func main() {
f, err := ioutil.TempFile("", "issue22660.go")
f, err := os.CreateTemp("", "issue22660.go")
if err != nil {
log.Fatal(err)
}
f.Close()
defer os.Remove(f.Name())

// path components from the //line directive must survive -trimpath and
// appear in error messages (since go.dev/issue/70478, as a path-component
// suffix of the resolved path, not as the bare prefix).
// path must appear in error messages even if we strip them with -trimpath
path := filepath.Join("users", "xxx", "go")
filename := filepath.Join(path, "foo.go")
var src bytes.Buffer
fmt.Fprintf(&src, "//line %s:1\n", filepath.Join(path, "foo.go"))

if err := ioutil.WriteFile(f.Name(), src.Bytes(), 0660); err != nil {
fmt.Fprintf(&src, "//line %s:1\n", filename)
if err := os.WriteFile(f.Name(), src.Bytes(), 0660); err != nil {
log.Fatal(err)
}

out, err := exec.Command("go", "tool", "compile", "-p=p", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput()
if err == nil {
log.Fatalf("expected compiling %s to fail", f.Name())
// The file only contains a line directive, w/o a package clause.
log.Fatalf("expected compiling %s to fail with syntax error", f.Name())
}

// After #70478 the resolved path is <tempdir>/users/xxx/go/foo.go,
// so the directive's components must appear as a path suffix.
want := filepath.Join(path, "foo.go")
if !strings.Contains(string(out), string(filepath.Separator)+want) {
log.Fatalf("expected path component (%s) in error message, got:\n%s", want, out)
// The error message position depends on the line directive.
// The resolved path is <tempdir>/filename, so the directive's components
// must appear as a path suffix in the error message's error position
// (go.dev/issue/70478).
if !strings.Contains(string(out), string(filepath.Separator)+filename) {
log.Fatalf("expected full path and filename (%s) in error message, got:\n%s", filename, out)
}
}
2 changes: 1 addition & 1 deletion test/fixedbugs/issue22662.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

// Since go.dev/issue/70478, the compiler resolves a relative filename in a
// //line directive against the directory of the source file, so the expected
// line directive against the directory of the source file, so the expected
// path may be a suffix of the actual filename rather than equal to it.
// Accept either an exact match or the file as a path-component suffix.
// Compiler-emitted paths are always slash-normalized (cmd/internal/objabi.AbsFile).
Expand Down
5 changes: 2 additions & 3 deletions test/fixedbugs/issue22662b.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
package main

import (
"io/ioutil"
"log"
"os"
"os/exec"
Expand All @@ -38,15 +37,15 @@ var tests = []struct {
}

func main() {
f, err := ioutil.TempFile("", "issue22662b.go")
f, err := os.CreateTemp("", "issue22662b.go")
if err != nil {
log.Fatal(err)
}
f.Close()
defer os.Remove(f.Name())

for _, test := range tests {
if err := ioutil.WriteFile(f.Name(), []byte(test.src), 0660); err != nil {
if err := os.WriteFile(f.Name(), []byte(test.src), 0660); err != nil {
log.Fatal(err)
}

Expand Down
Loading