From 86fa2551fb12338405721089d6db1b9d78e4f05e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Apr 2022 17:19:47 -0700 Subject: cmd/compile/internal/types2: permit parentheses around types in interfaces Before Go 1.18, an embedded type name in an interface could not be parenthesized. With generalized embedding of types in interfaces, where one might write ~(chan<- int) for clarity (making clear that the ~ applies to the entire channel type), it also makes sense to permit (chan<- int), or (int) for that matter. Adjust the parser accordingly to match the spec. (go/types already accepts the notation as specified by the spec.) Fixes #52391. Change-Id: Ifdd9a199c5ccc3473b2dac40dbca31d2df10d12b Reviewed-on: https://go-review.googlesource.com/c/go/+/400797 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/syntax/parser.go | 44 ++++------------------ .../compile/internal/syntax/testdata/issue52391.go | 17 +++++++++ 2 files changed, 24 insertions(+), 37 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue52391.go diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index f18d526877..9de6d4f45e 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1499,44 +1499,14 @@ func (p *parser) interfaceType() *InterfaceType { p.want(_Interface) p.want(_Lbrace) p.list("interface type", _Semi, _Rbrace, func() bool { - switch p.tok { - case _Name: - f := p.methodDecl() - if f.Name == nil { - f = p.embeddedElem(f) - } - typ.MethodList = append(typ.MethodList, f) - return false - - case _Lparen: - p.syntaxError("cannot parenthesize embedded type") - f := new(Field) - f.pos = p.pos() - p.next() - f.Type = p.qualifiedName(nil) - p.want(_Rparen) - typ.MethodList = append(typ.MethodList, f) - return false - - case _Operator: - if p.op == Tilde { - typ.MethodList = append(typ.MethodList, p.embeddedElem(nil)) - return false - } - - default: - pos := p.pos() - if t := p.typeOrNil(); t != nil { - f := new(Field) - f.pos = pos - f.Type = t - typ.MethodList = append(typ.MethodList, p.embeddedElem(f)) - return false - } + var f *Field + if p.tok == _Name { + f = p.methodDecl() } - - p.syntaxError("expecting method or embedded element") - p.advance(_Semi, _Rbrace) + if f == nil || f.Name == nil { + f = p.embeddedElem(f) + } + typ.MethodList = append(typ.MethodList, f) return false }) diff --git a/src/cmd/compile/internal/syntax/testdata/issue52391.go b/src/cmd/compile/internal/syntax/testdata/issue52391.go new file mode 100644 index 0000000000..f2098ceadb --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue52391.go @@ -0,0 +1,17 @@ +// Copyright 2022 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 p + +type _ interface { + int + (int) + (*int) + *([]byte) + ~(int) + (int) | (string) + (int) | ~(string) + (/* ERROR unexpected ~ */ ~int) + (int /* ERROR unexpected \| */ | /* ERROR unexpected string */ string /* ERROR unexpected \) */ ) +} -- cgit v1.2.3-54-g00ecf From 302f5ed21dad2cb99f3f63fd99228dc3ab480772 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Apr 2022 18:43:22 -0700 Subject: cmd/compile/internal/types2: don't crash in overflow check Be careful before accessing an operand's expr field (which may be nil in some rare cases). While at it, factor out position information so that it's only computed when there's an error, which is almost never. In go/types, remove an unnecessary argument to Checker.overflow. The code is otherwise ok as it's structured slightly differently due to the way positions are recorded in AST nodes. Fixes #52401. Change-Id: I447ebd9bb0c33eb6bff5e7b4d5aee37ceb0a4b14 Reviewed-on: https://go-review.googlesource.com/c/go/+/400798 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/expr.go | 51 ++++++++++++---------- .../types2/testdata/fixedbugs/issue52401.go | 11 +++++ src/go/types/expr.go | 12 ++--- src/go/types/testdata/fixedbugs/issue52401.go | 11 +++++ 4 files changed, 56 insertions(+), 29 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue52401.go create mode 100644 src/go/types/testdata/fixedbugs/issue52401.go diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index e0c22f5b03..27f290420b 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -89,21 +89,11 @@ func (check *Checker) op(m opPredicates, x *operand, op syntax.Operator) bool { func (check *Checker) overflow(x *operand) { assert(x.mode == constant_) - // If the corresponding expression is an operation, use the - // operator position rather than the start of the expression - // as error position. - pos := syntax.StartPos(x.expr) - what := "" // operator description, if any - if op, _ := x.expr.(*syntax.Operation); op != nil { - pos = op.Pos() - what = opName(op) - } - if x.val.Kind() == constant.Unknown { // TODO(gri) We should report exactly what went wrong. At the // moment we don't have the (go/constant) API for that. // See also TODO in go/constant/value.go. - check.error(pos, "constant result is not representable") + check.error(opPos(x.expr), "constant result is not representable") return } @@ -119,22 +109,37 @@ func (check *Checker) overflow(x *operand) { // Untyped integer values must not grow arbitrarily. const prec = 512 // 512 is the constant precision if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec { - check.errorf(pos, "constant %s overflow", what) + check.errorf(opPos(x.expr), "constant %s overflow", opName(x.expr)) x.val = constant.MakeUnknown() } } -// opName returns the name of an operation, or the empty string. -// Only operations that might overflow are handled. -func opName(e *syntax.Operation) string { - op := int(e.Op) - if e.Y == nil { - if op < len(op2str1) { - return op2str1[op] - } - } else { - if op < len(op2str2) { - return op2str2[op] +// opPos returns the position of the operator if x is an operation; +// otherwise it returns the start position of x. +func opPos(x syntax.Expr) syntax.Pos { + switch op := x.(type) { + case nil: + return nopos // don't crash + case *syntax.Operation: + return op.Pos() + default: + return syntax.StartPos(x) + } +} + +// opName returns the name of the operation if x is an operation +// that might overflow; otherwise it returns the empty string. +func opName(x syntax.Expr) string { + if e, _ := x.(*syntax.Operation); e != nil { + op := int(e.Op) + if e.Y == nil { + if op < len(op2str1) { + return op2str1[op] + } + } else { + if op < len(op2str2) { + return op2str2[op] + } } } return "" diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue52401.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue52401.go new file mode 100644 index 0000000000..c7efd8c718 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue52401.go @@ -0,0 +1,11 @@ +// Copyright 2022 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 p + +func _() { + const x = 0 + x /* ERROR cannot assign to x */ += 1 + x /* ERROR cannot assign to x */ ++ +} diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 977153512f..70914d5485 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -87,7 +87,7 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { // overflow checks that the constant x is representable by its type. // For untyped constants, it checks that the value doesn't become // arbitrarily large. -func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { +func (check *Checker) overflow(x *operand, opPos token.Pos) { assert(x.mode == constant_) if x.val.Kind() == constant.Unknown { @@ -115,8 +115,8 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { } } -// opName returns the name of an operation, or the empty string. -// Only operations that might overflow are handled. +// opName returns the name of the operation if x is an operation +// that might overflow; otherwise it returns the empty string. func opName(e ast.Expr) string { switch e := e.(type) { case *ast.BinaryExpr: @@ -213,7 +213,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { } x.val = constant.UnaryOp(e.Op, x.val, prec) x.expr = e - check.overflow(x, e.Op, x.Pos()) + check.overflow(x, x.Pos()) return } @@ -991,7 +991,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { if b, _ := e.(*ast.BinaryExpr); b != nil { opPos = b.OpPos } - check.overflow(x, op, opPos) + check.overflow(x, opPos) return } @@ -1171,7 +1171,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token } x.val = constant.BinaryOp(x.val, op, y.val) x.expr = e - check.overflow(x, op, opPos) + check.overflow(x, opPos) return } diff --git a/src/go/types/testdata/fixedbugs/issue52401.go b/src/go/types/testdata/fixedbugs/issue52401.go new file mode 100644 index 0000000000..c7efd8c718 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue52401.go @@ -0,0 +1,11 @@ +// Copyright 2022 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 p + +func _() { + const x = 0 + x /* ERROR cannot assign to x */ += 1 + x /* ERROR cannot assign to x */ ++ +} -- cgit v1.2.3-54-g00ecf From 104742fddae061b52c38e221697cf20ebd09bf10 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 Apr 2022 13:46:15 -0700 Subject: cmd/compile/internal/types2: use correct value of iota Fixes #52438. Change-Id: I5cbf8c448dba037e9e0c5fe8f209401d6bf7d43f Reviewed-on: https://go-review.googlesource.com/c/go/+/401134 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/resolver.go | 2 +- .../internal/types2/testdata/check/const0.go | 19 +++++++++++ src/go/types/testdata/check/const0.go | 19 +++++++++++ test/fixedbugs/issue52438.go | 39 ++++++++++++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue52438.go diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 95143cbed5..4f28c362c7 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -735,7 +735,7 @@ func (check *Checker) declStmt(list []syntax.Decl) { top := len(check.delayed) // iota is the index of the current constDecl within the group - if first < 0 || list[index-1].(*syntax.ConstDecl).Group != s.Group { + if first < 0 || s.Group == nil || list[index-1].(*syntax.ConstDecl).Group != s.Group { first = index last = nil } diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 5c64ecdfc8..5d498b6b2b 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -340,7 +340,7 @@ func (check *Checker) collectObjects() { case *syntax.ConstDecl: // iota is the index of the current constDecl within the group - if first < 0 || file.DeclList[index-1].(*syntax.ConstDecl).Group != s.Group { + if first < 0 || s.Group == nil || file.DeclList[index-1].(*syntax.ConstDecl).Group != s.Group { first = index last = nil } diff --git a/src/cmd/compile/internal/types2/testdata/check/const0.go b/src/cmd/compile/internal/types2/testdata/check/const0.go index 3cffdf904c..229c248643 100644 --- a/src/cmd/compile/internal/types2/testdata/check/const0.go +++ b/src/cmd/compile/internal/types2/testdata/check/const0.go @@ -349,6 +349,25 @@ const _ = unsafe.Sizeof(func() { assert(iota == 0) }) +// issue #52438 +const i1 = iota +const i2 = iota +const i3 = iota + +func _() { + assert(i1 == 0) + assert(i2 == 0) + assert(i3 == 0) + + const i4 = iota + const i5 = iota + const i6 = iota + + assert(i4 == 0) + assert(i5 == 0) + assert(i6 == 0) +} + // untyped constants must not get arbitrarily large const prec = 512 // internal maximum precision for integers const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1< Date: Tue, 15 Mar 2022 10:15:53 -0700 Subject: spec: clarify rules for type set construction of an interface Be explicit that we always mean non-interface types when we talk about sets of types. Also, clarify that the quantification "all non-interface types" means all such types in all possible programs, not just the current program. Per suggestion from Philip Wadler. Change-Id: Ibc7b5823164e547bfcee85d4e523e58c7c27ac8a Reviewed-on: https://go-review.googlesource.com/c/go/+/398655 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- doc/go_spec.html | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index b496e9e48f..b272cb5df6 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -1278,7 +1278,8 @@ then the File interface is implemented by both S1 and

Every type that is a member of the type set of an interface implements that interface. Any given type may implement several distinct interfaces. -For instance, all types implement the empty interface which stands for the set of all types: +For instance, all types implement the empty interface which stands for the set +of all (non-interface) types:

@@ -1380,7 +1381,7 @@ definition of an interface's type set as follows:
 		of its interface elements.
 	
 
-	
  • The type set of a method specification is the set of types +
  • The type set of a method specification is the set of all non-interface types whose method sets include that method.
  • @@ -1389,7 +1390,7 @@ definition of an interface's type set as follows:
  • The type set of a term of the form ~T - is the set of types whose underlying type is T. + is the set of all types whose underlying type is T.
  • The type set of a union of terms @@ -1398,6 +1399,15 @@ definition of an interface's type set as follows:
  • +

    +The quantification "the set of all non-interface types" refers not just to all (non-interface) +types declared in the program at hand, but all possible types in all possible programs, and +hence is infinite. +Similarly, given the set of all non-interface types that implement a particular method, the +intersection of the method sets of those types will contain exactly that method, even if all +types in the program at hand always pair that method with another method. +

    +

    By construction, an interface's type set never contains an interface type.

    -- cgit v1.2.3-54-g00ecf From cbc9e589053e7339c1e3c4d6e88c6c015792efce Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 12 Jan 2022 13:28:33 -0500 Subject: cmd/go/internal/base: in AppendPWD, check that PWD is absolute The POSIX standard requires the PWD variable to be an absolute path. Fixes #46832 Change-Id: I1938592538633e1a0a0958276f1fefc3c4808399 Reviewed-on: https://go-review.googlesource.com/c/go/+/378396 Run-TryBot: Bryan Mills Reviewed-by: Michael Matloob TryBot-Result: Gopher Robot --- src/cmd/go/internal/base/env.go | 12 ++++++++++-- src/cmd/go/internal/generate/generate_test.go | 17 +++++++++++------ src/cmd/go/internal/vcs/vcs.go | 16 +++++++++++++--- src/cmd/go/internal/work/buildid.go | 4 +--- src/cmd/go/internal/work/exec.go | 9 ++++++--- src/cmd/go/testdata/script/mod_list_direct.txt | 2 +- 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/cmd/go/internal/base/env.go b/src/cmd/go/internal/base/env.go index 5f2665d236..2f47300f2e 100644 --- a/src/cmd/go/internal/base/env.go +++ b/src/cmd/go/internal/base/env.go @@ -4,12 +4,20 @@ package base +import ( + "fmt" + "path/filepath" +) + // AppendPWD returns the result of appending PWD=dir to the environment base. // // The resulting environment makes os.Getwd more efficient for a subprocess // running in dir. func AppendPWD(base []string, dir string) []string { - // Internally we only use absolute paths, so dir is absolute. - // Even if dir is not absolute, no harm done. + // POSIX requires PWD to be absolute. + // Internally we only use absolute paths, so dir should already be absolute. + if !filepath.IsAbs(dir) { + panic(fmt.Sprintf("AppendPWD with relative path %q", dir)) + } return append(base, "PWD="+dir) } diff --git a/src/cmd/go/internal/generate/generate_test.go b/src/cmd/go/internal/generate/generate_test.go index 15b1279f36..d61ecf104a 100644 --- a/src/cmd/go/internal/generate/generate_test.go +++ b/src/cmd/go/internal/generate/generate_test.go @@ -5,7 +5,9 @@ package generate import ( + "internal/testenv" "os" + "path/filepath" "reflect" "runtime" "testing" @@ -41,10 +43,11 @@ var splitTests = []splitTest{ } func TestGenerateCommandParse(t *testing.T) { + dir := filepath.Join(testenv.GOROOT(t), "src", "sys") g := &Generator{ r: nil, // Unused here. - path: "/usr/ken/sys/proc.go", - dir: "/usr/ken/sys", + path: filepath.Join(dir, "proc.go"), + dir: dir, file: "proc.go", pkg: "sys", commands: make(map[string][]string), @@ -84,10 +87,11 @@ var defEnvMap = map[string]string{ // before executing the test. i.e., execute the split as if it // processing that source line. func TestGenerateCommandShorthand(t *testing.T) { + dir := filepath.Join(testenv.GOROOT(t), "src", "sys") g := &Generator{ r: nil, // Unused here. - path: "/usr/ken/sys/proc.go", - dir: "/usr/ken/sys", + path: filepath.Join(dir, "proc.go"), + dir: dir, file: "proc.go", pkg: "sys", commands: make(map[string][]string), @@ -222,10 +226,11 @@ var splitTestsLines = []splitTestWithLine{ // before executing the test. i.e., execute the split as if it // processing that source line. func TestGenerateCommandShortHand2(t *testing.T) { + dir := filepath.Join(testenv.GOROOT(t), "src", "sys") g := &Generator{ r: nil, // Unused here. - path: "/usr/ken/sys/proc.go", - dir: "/usr/ken/sys", + path: filepath.Join(dir, "proc.go"), + dir: dir, file: "proc.go", pkg: "sys", commands: make(map[string][]string), diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 2acabf7aaf..77208ab762 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -669,7 +669,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 { os.Stderr.Write(ee.Stderr) } else { - fmt.Fprintf(os.Stderr, err.Error()) + fmt.Fprintln(os.Stderr, err.Error()) } } } @@ -678,14 +678,24 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ // Ping pings to determine scheme to use. func (v *Cmd) Ping(scheme, repo string) error { - return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo) + // Run the ping command in an arbitrary working directory, + // but don't let the current working directory pollute the results. + // In module mode, we expect GOMODCACHE to exist and be a safe place for + // commands; in GOPATH mode, we expect that to be true of GOPATH/src. + dir := cfg.GOMODCACHE + if !cfg.ModulesEnabled { + dir = filepath.Join(cfg.BuildContext.GOPATH, "src") + } + os.MkdirAll(dir, 0777) // Ignore errors — if unsuccessful, the command will likely fail. + + return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo) } // Create creates a new copy of repo in dir. // The parent of dir must exist; dir must not. func (v *Cmd) Create(dir, repo string) error { for _, cmd := range v.CreateCmd { - if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil { + if err := v.run(filepath.Dir(dir), cmd, "dir", dir, "repo", repo); err != nil { return err } } diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 76335e9bb1..ac98aa344c 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -160,7 +160,6 @@ func (b *Builder) toolID(name string) string { cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full") cmd := exec.Command(cmdline[0], cmdline[1:]...) - cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr @@ -219,9 +218,8 @@ func (b *Builder) gccToolID(name, language string) (string, error) { // compile an empty file on standard input. cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-") cmd := exec.Command(cmdline[0], cmdline[1:]...) - cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir) // Force untranslated output so that we see the string "version". - cmd.Env = append(cmd.Env, "LC_ALL=C") + cmd.Env = append(os.Environ(), "LC_ALL=C") out, err := cmd.CombinedOutput() if err != nil { return "", fmt.Errorf("%s: %v; output: %q", name, err, out) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 9c9d58b2a1..f0e6c80029 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2116,8 +2116,11 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([ cmd.Stderr = &buf cleanup := passLongArgsInResponseFiles(cmd) defer cleanup() - cmd.Dir = dir - cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir) + cmd.Env = os.Environ() + if dir != "." { + cmd.Dir = dir + cmd.Env = base.AppendPWD(cmd.Env, dir) + } // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools. // It doesn't really matter if -toolexec isn't being used. @@ -3071,7 +3074,7 @@ var ( ) func (b *Builder) swigDoVersionCheck() error { - out, err := b.runOut(nil, "", nil, "swig", "-version") + out, err := b.runOut(nil, ".", nil, "swig", "-version") if err != nil { return err } diff --git a/src/cmd/go/testdata/script/mod_list_direct.txt b/src/cmd/go/testdata/script/mod_list_direct.txt index 9b7a04c504..3aa1881554 100644 --- a/src/cmd/go/testdata/script/mod_list_direct.txt +++ b/src/cmd/go/testdata/script/mod_list_direct.txt @@ -10,7 +10,7 @@ env GOSUMDB=off # For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file, # which would produce a hard error at the subsequent call to GoMod. -go get +go get -v -- go.mod -- module example.com -- cgit v1.2.3-54-g00ecf From 17f8d98a4adf8386e63a0d2902ff42ca5e80996e Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 18 Apr 2022 13:12:43 -0400 Subject: go/internal/srcimporter: add context to cgo errors An error message like "could not import os/user (exit status 1)" (observed in https://go.dev/issue/52407) is fairly inscrutable. On the other hand, srcimporter doesn't report errors with quite enough structure to dump the entire stderr output from 'go tool cgo' without potentially overwhelming the caller. Here, we split the difference by describing which command failed but not printing the output of that command. For #52407, that would at least provide a stronger clue connecting to #52408. Change-Id: Iabdc95b17ba20a0f6ff38e5c7084e5081e1ef5e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/400817 Run-TryBot: Bryan Mills Reviewed-by: Matthew Dempsky Auto-Submit: Bryan Mills TryBot-Result: Gopher Robot --- src/go/internal/srcimporter/srcimporter.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/go/internal/srcimporter/srcimporter.go b/src/go/internal/srcimporter/srcimporter.go index d7ec6691bc..ea6f01280a 100644 --- a/src/go/internal/srcimporter/srcimporter.go +++ b/src/go/internal/srcimporter/srcimporter.go @@ -136,7 +136,7 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type setUsesCgo(&conf) file, err := p.cgo(bp) if err != nil { - return nil, err + return nil, fmt.Errorf("error processing cgo for package %q: %w", bp.ImportPath, err) } files = append(files, file) } @@ -223,9 +223,9 @@ func (p *Importer) cgo(bp *build.Package) (*ast.File, error) { args = append(args, bp.CgoCPPFLAGS...) if len(bp.CgoPkgConfig) > 0 { cmd := exec.Command("pkg-config", append([]string{"--cflags"}, bp.CgoPkgConfig...)...) - out, err := cmd.CombinedOutput() + out, err := cmd.Output() if err != nil { - return nil, err + return nil, fmt.Errorf("pkg-config --cflags: %w", err) } args = append(args, strings.Fields(string(out))...) } @@ -237,7 +237,7 @@ func (p *Importer) cgo(bp *build.Package) (*ast.File, error) { cmd := exec.Command(args[0], args[1:]...) cmd.Dir = bp.Dir if err := cmd.Run(); err != nil { - return nil, err + return nil, fmt.Errorf("go tool cgo: %w", err) } return parser.ParseFile(p.fset, filepath.Join(tmpdir, "_cgo_gotypes.go"), nil, 0) -- cgit v1.2.3-54-g00ecf From 338a81741a9aecba1a80014eced5cb2d3852d8eb Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 20 Apr 2022 11:17:59 -0400 Subject: crypto/rand: apply the same max read size on Illumos as on Solaris This case was missed in CL 370894, and masked by the lack of an Illumos TryBot. Fixes #52452. Change-Id: I7cda193e33c11a9d04eb888fdb5ec9218e6ed1b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/401294 Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Filippo Valsorda --- src/crypto/rand/rand_getrandom.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/rand/rand_getrandom.go b/src/crypto/rand/rand_getrandom.go index cb31a5687a..478aa5c459 100644 --- a/src/crypto/rand/rand_getrandom.go +++ b/src/crypto/rand/rand_getrandom.go @@ -21,7 +21,7 @@ func init() { // is returned by a single call to getrandom() on systems where int // has a size of 32 bits. maxGetRandomRead = (1 << 25) - 1 - case "freebsd", "dragonfly", "solaris": + case "freebsd", "dragonfly", "solaris", "illumos": maxGetRandomRead = 1 << 8 default: panic("no maximum specified for GetRandom") -- cgit v1.2.3-54-g00ecf From a2f7d9d95a84dedb6909bf1907d6857c2c4a2ef5 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 20 Apr 2022 08:58:42 -0700 Subject: net/http: deflake TestTransportConnectionCloseOnRequest Fixes #52450 (hopefully) Change-Id: Ib723f8efb4a13af1b98c25cd02935425172d01e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/401314 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Reviewed-by: Damien Neil --- src/net/http/export_test.go | 9 +++++++++ src/net/http/transport_test.go | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go index a849327f45..205ca83f40 100644 --- a/src/net/http/export_test.go +++ b/src/net/http/export_test.go @@ -306,3 +306,12 @@ func ExportCloseTransportConnsAbruptly(tr *Transport) { } tr.idleMu.Unlock() } + +// ResponseWriterConnForTesting returns w's underlying connection, if w +// is a regular *response ResponseWriter. +func ResponseWriterConnForTesting(w ResponseWriter) (c net.Conn, ok bool) { + if r, ok := w.(*response); ok { + return r.conn.rwc, true + } + return nil, false +} diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 6fcb458296..acdfae39ed 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -57,6 +57,12 @@ var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) { } w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close)) w.Write([]byte(r.RemoteAddr)) + + // Include the address of the net.Conn in addition to the RemoteAddr, + // in case kernels reuse source ports quickly (see Issue 52450) + if c, ok := ResponseWriterConnForTesting(w); ok { + fmt.Fprintf(w, ", %T %p", c, c) + } }) // testCloseConn is a net.Conn tracked by a testConnSet. @@ -240,6 +246,12 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) { connSet.check(t) } +// TestTransportConnectionCloseOnRequest tests that the Transport's doesn't reuse +// an underlying TCP connection after making an http.Request with Request.Close set. +// +// It tests the behavior by making an HTTP request to a server which +// describes the source source connection it got (remote port number + +// address of its net.Conn). func TestTransportConnectionCloseOnRequest(t *testing.T) { defer afterTest(t) ts := httptest.NewServer(hostPortHandler) @@ -250,7 +262,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) { c := ts.Client() tr := c.Transport.(*Transport) tr.Dial = testDial - for _, connectionClose := range []bool{false, true} { + for _, reqClose := range []bool{false, true} { fetch := func(n int) string { req := new(Request) var err error @@ -262,29 +274,37 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) { req.Proto = "HTTP/1.1" req.ProtoMajor = 1 req.ProtoMinor = 1 - req.Close = connectionClose + req.Close = reqClose res, err := c.Do(req) if err != nil { - t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err) + t.Fatalf("error in Request.Close=%v, req #%d, Do: %v", reqClose, n, err) } - if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(connectionClose); got != want { - t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v", - connectionClose, got, !connectionClose) + if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(reqClose); got != want { + t.Errorf("for Request.Close = %v; handler's X-Saw-Close was %v; want %v", + reqClose, got, !reqClose) } body, err := io.ReadAll(res.Body) if err != nil { - t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err) + t.Fatalf("for Request.Close=%v, on request %v/2: ReadAll: %v", reqClose, n, err) } return string(body) } body1 := fetch(1) body2 := fetch(2) - bodiesDiffer := body1 != body2 - if bodiesDiffer != connectionClose { - t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q", - connectionClose, bodiesDiffer, body1, body2) + + got := 1 + if body1 != body2 { + got++ + } + want := 1 + if reqClose { + want = 2 + } + if got != want { + t.Errorf("for Request.Close=%v: server saw %v unique connections, wanted %v\n\nbodies were: %q and %q", + reqClose, got, want, body1, body2) } tr.CloseIdleConnections() -- cgit v1.2.3-54-g00ecf From 58340240576a9ad254d90da4570e5e6afb913959 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 20 Apr 2022 12:24:09 -0400 Subject: cmd/link: fix StackCheckOutput on AIX This test forces GOARCH to amd64, but currently uses the default GOOS. This works on every OS that supports amd64, which is every OS we support except AIX. Hence, on AIX this fails with an unsupported GOOS/GOARCH combination. Fix this by forcing GOOS to linux. Fixes #52451. Change-Id: I9321dd6386c7ef0fe2b47d77ed900aafc53f2a46 Reviewed-on: https://go-review.googlesource.com/c/go/+/401334 Run-TryBot: Austin Clements Reviewed-by: Bryan Mills Auto-Submit: Austin Clements TryBot-Result: Gopher Robot --- src/cmd/link/internal/ld/stackcheck.go | 2 +- src/cmd/link/internal/ld/stackcheck_test.go | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/cmd/link/internal/ld/stackcheck.go b/src/cmd/link/internal/ld/stackcheck.go index 520e4d67b5..f0e1367068 100644 --- a/src/cmd/link/internal/ld/stackcheck.go +++ b/src/cmd/link/internal/ld/stackcheck.go @@ -101,7 +101,7 @@ func (ctxt *Link) doStackCheck() { // the same function multiple times at different // depths, but lets us find all paths. for _, root := range roots { - ctxt.Errorf(root, "nosplit stack overflow") + ctxt.Errorf(root, "nosplit stack over %d byte limit", limit) chain := []stackCheckChain{{stackCheckEdge{0, root}, false}} sc.report(root, limit, &chain) } diff --git a/src/cmd/link/internal/ld/stackcheck_test.go b/src/cmd/link/internal/ld/stackcheck_test.go index 21dbf2b3fd..2089badbe9 100644 --- a/src/cmd/link/internal/ld/stackcheck_test.go +++ b/src/cmd/link/internal/ld/stackcheck_test.go @@ -5,13 +5,12 @@ package ld import ( - "cmd/internal/objabi" - "cmd/internal/sys" "fmt" "internal/testenv" "os" "os/exec" "regexp" + "strconv" "testing" ) @@ -24,7 +23,7 @@ func TestStackCheckOutput(t *testing.T) { cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", os.DevNull, "./testdata/stackcheck") // The rules for computing frame sizes on all of the // architectures are complicated, so just do this on amd64. - cmd.Env = append(os.Environ(), "GOARCH=amd64") + cmd.Env = append(os.Environ(), "GOARCH=amd64", "GOOS=linux") outB, err := cmd.CombinedOutput() if err == nil { @@ -34,13 +33,13 @@ func TestStackCheckOutput(t *testing.T) { t.Logf("linker output:\n%s", out) - // Construct expected stanzas - arch := sys.ArchAMD64 - call := 0 - if !arch.HasLR { - call = arch.RegSize + // Get expected limit. + limitRe := regexp.MustCompile("nosplit stack over ([0-9]+) byte limit") + m := limitRe.FindStringSubmatch(out) + if m == nil { + t.Fatalf("no overflow errors in output") } - limit := objabi.StackLimit - call + limit, _ := strconv.Atoi(m[1]) wantMap := map[string]string{ "main.startSelf": fmt.Sprintf( @@ -67,7 +66,7 @@ func TestStackCheckOutput(t *testing.T) { } // Parse stanzas - stanza := regexp.MustCompile(`^(.*): nosplit stack overflow\n(.*\n(?: .*\n)*)`) + stanza := regexp.MustCompile(`^(.*): nosplit stack over [0-9]+ byte limit\n(.*\n(?: .*\n)*)`) // Strip comments from cmd/go out = regexp.MustCompile(`(?m)^#.*\n`).ReplaceAllString(out, "") for len(out) > 0 { -- cgit v1.2.3-54-g00ecf From c75befeec2a8ef2fea3c41da589ca0ffddda506f Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 14 Mar 2022 13:00:03 -0400 Subject: cmd/go: don't compute Deps fields if they're not needed If the user provides the -json flag to explicitly specify fields, but doesn't specify the Deps or DepsErrors fields, skip computing the deps fields. For #29666 Change-Id: I15596c374aba1af13bdf5808d11d54abdc838667 Reviewed-on: https://go-review.googlesource.com/c/go/+/392495 Reviewed-by: Bryan Mills Run-TryBot: Michael Matloob Auto-Submit: Michael Matloob Reviewed-by: Michael Matloob TryBot-Result: Gopher Robot --- src/cmd/go/internal/list/list.go | 7 +++++++ src/cmd/go/internal/load/pkg.go | 10 +++++++++- src/cmd/go/testdata/script/list_json_fields.txt | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 17864e1da7..e9e0910f32 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -568,6 +568,13 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { IgnoreImports: *listFind, ModResolveTests: *listTest, LoadVCS: true, + // SuppressDeps is set if the user opts to explicitly ask for the json fields they + // need, don't ask for Deps or DepsErrors. It's not set when using a template string, + // even if *listFmt doesn't contain .Deps because Deps are used to find import cycles + // for test variants of packages and users who have been providing format strings + // might not expect those errors to stop showing up. + // See issue #52443. + SuppressDeps: !listJsonFields.needAny("Deps", "DepsErrors"), } pkgs := load.PackagesAndErrors(ctx, pkgOpts, args) if !*listE { diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index e43117f3d3..51bf7176d1 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1938,7 +1938,9 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * } } p.Internal.Imports = imports - p.collectDeps() + if !opts.SuppressDeps { + p.collectDeps() + } if p.Error == nil && p.Name == "main" && !p.Internal.ForceLibrary && len(p.DepsErrors) == 0 { // TODO(bcmills): loading VCS metadata can be fairly slow. // Consider starting this as a background goroutine and retrieving the result @@ -2679,6 +2681,12 @@ type PackageOpts struct { // LoadVCS controls whether we also load version-control metadata for main packages. LoadVCS bool + + // NeedDepsFields is true if the caller does not need Deps and DepsErrors to be populated + // on the package. TestPackagesAndErrors examines the Deps field to determine if the test + // variant has an import cycle, so SuppressDeps should not be set if TestPackagesAndErrors + // will be called on the package. + SuppressDeps bool } // PackagesAndErrors returns the packages named by the command line arguments diff --git a/src/cmd/go/testdata/script/list_json_fields.txt b/src/cmd/go/testdata/script/list_json_fields.txt index 58c9efa162..9b8edc6d7f 100644 --- a/src/cmd/go/testdata/script/list_json_fields.txt +++ b/src/cmd/go/testdata/script/list_json_fields.txt @@ -21,6 +21,11 @@ cmp stdout want-json-name.txt go list -json=ImportPath,Name,GoFiles,Imports cmp stdout want-json-multiple.txt +# Test -json= with Deps outputs the Deps field. +go list -json=Deps +stdout '"Deps": \[' +stdout '"errors",' + -- go.mod -- module example.com/a -- cgit v1.2.3-54-g00ecf From e49b80a754c3df1a82d089a16a46ea8946d5a00b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 20 Apr 2022 12:05:30 -0700 Subject: cmd/compile/internal/syntax: correct an error string When we have an error in a function type used in an expression we don't know until we see an opening { whether we have a function literal or a function type. Use "function type" as context because that's always correct in the specific error message. Change-Id: I9aad8fcddf31ae53daa53cebd2c2001f08eabde0 Reviewed-on: https://go-review.googlesource.com/c/go/+/401316 Reviewed-by: Ian Lance Taylor Run-TryBot: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/syntax/parser.go | 2 +- src/cmd/compile/internal/syntax/testdata/issue48382.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 9de6d4f45e..fe1c76e81b 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -991,7 +991,7 @@ func (p *parser) operand(keep_parens bool) Expr { case _Func: pos := p.pos() p.next() - _, ftyp := p.funcType("function literal") + _, ftyp := p.funcType("function type") if p.tok == _Lbrace { p.xnest++ diff --git a/src/cmd/compile/internal/syntax/testdata/issue48382.go b/src/cmd/compile/internal/syntax/testdata/issue48382.go index c00fee6f82..7c024a051f 100644 --- a/src/cmd/compile/internal/syntax/testdata/issue48382.go +++ b/src/cmd/compile/internal/syntax/testdata/issue48382.go @@ -8,7 +8,8 @@ type _ func /* ERROR function type must have no type parameters */ [ /* ERROR em type _ func /* ERROR function type must have no type parameters */ [ x /* ERROR missing type constraint */ ]() type _ func /* ERROR function type must have no type parameters */ [P any]() -var _ = func /* ERROR function literal must have no type parameters */ [P any]() {} +var _ = (func /* ERROR function type must have no type parameters */ [P any]())(nil) +var _ = func /* ERROR function type must have no type parameters */ [P any]() {} type _ interface{ m /* ERROR interface method must have no type parameters */ [P any]() -- cgit v1.2.3-54-g00ecf From 8b364451e2e2f2f816ed877a4639d9342279f299 Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Mon, 18 Apr 2022 11:02:26 +0100 Subject: net/http: drop mimesniff for audio/basic The WHATWG Mime Sniffing Standard we follow dropped support for .snd / audio/basic. https://github.com/whatwg/mimesniff/issues/151 Change-Id: Iae1bd8b29063b06b5b3909a944e12ead5974a526 Reviewed-on: https://go-review.googlesource.com/c/go/+/400754 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick Auto-Submit: Brad Fitzpatrick TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Damien Neil --- src/net/http/sniff.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/net/http/sniff.go b/src/net/http/sniff.go index 67a7151b0c..ac18ab979d 100644 --- a/src/net/http/sniff.go +++ b/src/net/http/sniff.go @@ -128,11 +128,6 @@ var sniffSignatures = []sniffSig{ // Audio and Video types // Enforce the pattern match ordering as prescribed in // https://mimesniff.spec.whatwg.org/#matching-an-audio-or-video-type-pattern - &maskedSig{ - mask: []byte("\xFF\xFF\xFF\xFF"), - pat: []byte(".snd"), - ct: "audio/basic", - }, &maskedSig{ mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"), pat: []byte("FORM\x00\x00\x00\x00AIFF"), -- cgit v1.2.3-54-g00ecf From 6de00888e4720b7fa23ef2ce294bc3e81b866b0f Mon Sep 17 00:00:00 2001 From: Phil Kulin Date: Wed, 20 Apr 2022 14:13:29 +0000 Subject: reflect: remove unused overflowPad variable overflowPad variable in bucketOf function is a holdover from a NaCl port and never used now. Change-Id: Ib68fdb054e1b6a655ffbfd34521a3f8773a22694 GitHub-Last-Rev: f281be9c115a87605fd28b39c0b09eed54cc774a GitHub-Pull-Request: golang/go#52449 Reviewed-on: https://go-review.googlesource.com/c/go/+/401274 Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Auto-Submit: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor --- src/reflect/type.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index e888266475..97040b5188 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2244,15 +2244,14 @@ func bucketOf(ktyp, etyp *rtype) *rtype { } // Prepare GC data if any. - // A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+2*ptrSize bytes, - // or 2072 bytes, or 259 pointer-size words, or 33 bytes of pointer bitmap. + // A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+ptrSize bytes, + // or 2064 bytes, or 258 pointer-size words, or 33 bytes of pointer bitmap. // Note that since the key and value are known to be <= 128 bytes, // they're guaranteed to have bitmaps instead of GC programs. var gcdata *byte var ptrdata uintptr - var overflowPad uintptr - size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + goarch.PtrSize + size := bucketSize*(1+ktyp.size+etyp.size) + goarch.PtrSize if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 { panic("reflect: bad size computation in MapOf") } @@ -2271,7 +2270,6 @@ func bucketOf(ktyp, etyp *rtype) *rtype { emitGCMask(mask, base, etyp, bucketSize) } base += bucketSize * etyp.size / goarch.PtrSize - base += overflowPad / goarch.PtrSize word := base mask[word/8] |= 1 << (word % 8) @@ -2291,9 +2289,6 @@ func bucketOf(ktyp, etyp *rtype) *rtype { ptrdata: ptrdata, gcdata: gcdata, } - if overflowPad > 0 { - b.align = 8 - } s := "bucket(" + ktyp.String() + "," + etyp.String() + ")" b.str = resolveReflectName(newName(s, "", false)) return b -- cgit v1.2.3-54-g00ecf From ebe1435fbb50bb82bfca53063e8daba4f870ec8d Mon Sep 17 00:00:00 2001 From: zhangyunhao Date: Mon, 18 Apr 2022 15:23:20 +0800 Subject: runtime: add fastrand64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support fastrand64 in the runtime, although fastrand uses wyrand to generate 64-bit random number, it still returns uint32. In some cases, we need to generate a 64-bit random number, the new API would be faster and easier to use, and at least we can use the new function in these places: src/net/dnsclient.go:randInt() src/hash/maphash/maphash.go:MakeSeed() src/runtime/map.go:mapiterinit() name time/op Fastrand-16 0.09ns ± 5% Fastrand64-16 0.09ns ± 6% Change-Id: Ibb97378c7ca59bc7dc15535d4872fa58ea112e6a Reviewed-on: https://go-review.googlesource.com/c/go/+/400734 Reviewed-by: Keith Randall Run-TryBot: Keith Randall Auto-Submit: Keith Randall Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/runtime/export_test.go | 1 + src/runtime/rand_test.go | 8 ++++++++ src/runtime/stubs.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index af27050bfd..8a81f42ca0 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -277,6 +277,7 @@ func CountPagesInUse() (pagesInUse, counted uintptr) { } func Fastrand() uint32 { return fastrand() } +func Fastrand64() uint64 { return fastrand64() } func Fastrandn(n uint32) uint32 { return fastrandn(n) } type ProfBuf profBuf diff --git a/src/runtime/rand_test.go b/src/runtime/rand_test.go index 1b84c79d24..92d07ebada 100644 --- a/src/runtime/rand_test.go +++ b/src/runtime/rand_test.go @@ -18,6 +18,14 @@ func BenchmarkFastrand(b *testing.B) { }) } +func BenchmarkFastrand64(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Fastrand64() + } + }) +} + func BenchmarkFastrandHashiter(b *testing.B) { var m = make(map[int]int, 10) for i := 0; i < 10; i++ { diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 8c4ab3ed4e..ca0cd1ba25 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -157,6 +157,45 @@ func fastrandn(n uint32) uint32 { return uint32(uint64(fastrand()) * uint64(n) >> 32) } +func fastrand64() uint64 { + mp := getg().m + // Implement wyrand: https://github.com/wangyi-fudan/wyhash + // Only the platform that math.Mul64 can be lowered + // by the compiler should be in this list. + if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64| + goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le| + goarch.IsS390x|goarch.IsRiscv64 == 1 { + mp.fastrand += 0xa0761d6478bd642f + hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db) + return hi ^ lo + } + + // Implement xorshift64+: 2 32-bit xorshift sequences added together. + // Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf + // This generator passes the SmallCrush suite, part of TestU01 framework: + // http://simul.iro.umontreal.ca/testu01/tu01.html + t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand)) + s1, s0 := t[0], t[1] + s1 ^= s1 << 17 + s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 + r := uint64(s0 + s1) + + s0, s1 = s1, s0 + s1 ^= s1 << 17 + s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 + r += uint64(s0+s1) << 32 + + t[0], t[1] = s0, s1 + return r +} + +func fastrandu() uint { + if goarch.PtrSize == 4 { + return uint(fastrand()) + } + return uint(fastrand64()) +} + //go:linkname sync_fastrandn sync.fastrandn func sync_fastrandn(n uint32) uint32 { return fastrandn(n) } -- cgit v1.2.3-54-g00ecf From ab9d31da9e088a271e656120a3d99cd3b1103ab6 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Tue, 19 Apr 2022 15:11:37 +1000 Subject: cmd/go/internal/test: wrap os.Stdout always There is an issue where 'go test' will hang after the tests complete if a test starts a sub-process that does not exit (see #24050). However, go test only exhibits that behavior when a package name is explicitly passed as an argument. If 'go test' is invoked without any package arguments then the package in the working directory is assumed, however in that case (and only that case) os.Stdout is used as the test process's cmd.Stdout, which does *not* cause 'go test' wait for the sub-process to exit (see #23019). This change wraps os.Stdout in an io.Writer struct in this case, hiding the *os.File from the os/exec package, causing cmd.Wait to always wait for the full output from the test process and any of its sub-processes. In other words, this makes 'go test' exhibit the same behavior as 'go test .' (or 'go test ./...' and so on). Update #23019 Update #24050 Change-Id: Ica09bf156f3b017f9a31aad91ed0f16a7837195b Reviewed-on: https://go-review.googlesource.com/c/go/+/400877 Reviewed-by: Bryan Mills Run-TryBot: Andrew Gerrand Auto-Submit: Andrew Gerrand TryBot-Result: Gopher Robot Reviewed-by: Andrew Gerrand Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/test/test.go | 6 ++++- src/cmd/go/testdata/script/test_output_wait.txt | 35 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/test_output_wait.txt diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 50e6d5201b..f2d2290dbb 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1261,7 +1261,11 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. return nil } - var stdout io.Writer = os.Stdout + // The os/exec package treats an *os.File differently to an io.Writer. + // Embed os.Stdout in an io.Writer struct so that we get the same + // behavior regardless of whether we wrap it below. + // See golang.org/issue/24050 + var stdout io.Writer = struct{ io.Writer }{os.Stdout} var err error if testJSON { json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp) diff --git a/src/cmd/go/testdata/script/test_output_wait.txt b/src/cmd/go/testdata/script/test_output_wait.txt new file mode 100644 index 0000000000..878b108612 --- /dev/null +++ b/src/cmd/go/testdata/script/test_output_wait.txt @@ -0,0 +1,35 @@ +# Wait for test output from sub-processes whether or not the package name is +# provided on the command-line. +go test -v +stdout 'PASS\s+WAIT\s+ok' +go test -v . +stdout 'PASS\s+WAIT\s+ok' + +-- go.mod -- +module x + +-- x_test.go -- +package x + +import ( + "os" + "os/exec" + "testing" +) + +func TestMain(m *testing.M) { + if os.Getenv("WAIT") == "true" { + os.Stdout.Write([]byte("WAIT\n")) + return + } + m.Run() +} + +func TestWait(t *testing.T) { + cmd := exec.Command(os.Args[0]) + cmd.Env = []string{"WAIT=true"} + cmd.Stdout = os.Stdout + if err := cmd.Start(); err != nil { + t.Fatal(err) + } +} -- cgit v1.2.3-54-g00ecf From aa242555412c29f8af3da7d92067577c6b089c3a Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 19 Apr 2022 15:54:50 -0400 Subject: os/exec: preserve original order of entries in dedupEnv Once #50599 is implemented, the entries will be observable via the Environ method. I find it confusing for later entries in the list to jump arbitrarily far forward based on entries for the same key that no longer exist. This also fixes the deduplication logic for the degenerate Windows keys observed in #49886, which were previously deduplicated as empty keys. (It does not do anything about the even-more-degenerate keys observed in #52436.) For #50599. Change-Id: Ia7cd2200ec34ccc4b9d18631cb513194dc420c25 Reviewed-on: https://go-review.googlesource.com/c/go/+/401339 Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills TryBot-Result: Gopher Robot --- src/os/exec/env_test.go | 16 ++++++++++++++-- src/os/exec/exec.go | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/os/exec/env_test.go b/src/os/exec/env_test.go index b5ac398c27..112f1e654a 100644 --- a/src/os/exec/env_test.go +++ b/src/os/exec/env_test.go @@ -18,17 +18,29 @@ func TestDedupEnv(t *testing.T) { { noCase: true, in: []string{"k1=v1", "k2=v2", "K1=v3"}, - want: []string{"K1=v3", "k2=v2"}, + want: []string{"k2=v2", "K1=v3"}, }, { noCase: false, in: []string{"k1=v1", "K1=V2", "k1=v3"}, - want: []string{"k1=v3", "K1=V2"}, + want: []string{"K1=V2", "k1=v3"}, }, { in: []string{"=a", "=b", "foo", "bar"}, want: []string{"=b", "foo", "bar"}, }, + { + // #49886: preserve weird Windows keys with leading "=" signs. + noCase: true, + in: []string{`=C:=C:\golang`, `=D:=D:\tmp`, `=D:=D:\`}, + want: []string{`=C:=C:\golang`, `=D:=D:\`}, + }, + { + // #52436: preserve invalid key-value entries (for now). + // (Maybe filter them out or error out on them at some point.) + in: []string{"dodgy", "entries"}, + want: []string{"dodgy", "entries"}, + }, } for _, tt := range tests { got := dedupEnvCase(tt.noCase, tt.in) diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index 845b737e28..58f8bbf84d 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -745,24 +745,47 @@ func dedupEnv(env []string) []string { // dedupEnvCase is dedupEnv with a case option for testing. // If caseInsensitive is true, the case of keys is ignored. func dedupEnvCase(caseInsensitive bool, env []string) []string { + // Construct the output in reverse order, to preserve the + // last occurrence of each key. out := make([]string, 0, len(env)) - saw := make(map[string]int, len(env)) // key => index into out - for _, kv := range env { - k, _, ok := strings.Cut(kv, "=") - if !ok { - out = append(out, kv) + saw := make(map[string]bool, len(env)) + for n := len(env); n > 0; n-- { + kv := env[n-1] + + i := strings.Index(kv, "=") + if i == 0 { + // We observe in practice keys with a single leading "=" on Windows. + // TODO(#49886): Should we consume only the first leading "=" as part + // of the key, or parse through arbitrarily many of them until a non-"="? + i = strings.Index(kv[1:], "=") + 1 + } + if i < 0 { + if kv != "" { + // The entry is not of the form "key=value" (as it is required to be). + // Leave it as-is for now. + // TODO(#52436): should we strip or reject these bogus entries? + out = append(out, kv) + } continue } + k := kv[:i] if caseInsensitive { k = strings.ToLower(k) } - if dupIdx, isDup := saw[k]; isDup { - out[dupIdx] = kv + if saw[k] { continue } - saw[k] = len(out) + + saw[k] = true out = append(out, kv) } + + // Now reverse the slice to restore the original order. + for i := 0; i < len(out)/2; i++ { + j := len(out) - i - 1 + out[i], out[j] = out[j], out[i] + } + return out } -- cgit v1.2.3-54-g00ecf From 1715a86721164bee98d95b16c78529cdd7dacc9c Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 10 Feb 2022 09:47:49 -0800 Subject: crypto/tls: reject duplicate extensions Does what it says on the tin. Fixes #51088 Change-Id: I12c0fa6bba1c1ce96c1ad31ba387c77a93f801c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/384894 Reviewed-by: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Gopher Robot Reviewed-by: Damien Neil --- src/crypto/tls/handshake_messages.go | 12 ++++++++++++ src/crypto/tls/handshake_messages_test.go | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index 17cf85910f..7ab0f100b8 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -384,6 +384,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -392,6 +393,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionServerName: // RFC 6066, Section 3 @@ -750,6 +756,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -758,6 +765,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionStatusRequest: m.ocspStapling = true diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go index cc427bf72a..49452da8b4 100644 --- a/src/crypto/tls/handshake_messages_test.go +++ b/src/crypto/tls/handshake_messages_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "encoding/hex" "math/rand" "reflect" "strings" @@ -463,3 +464,23 @@ func TestRejectEmptySCT(t *testing.T) { t.Fatal("Unmarshaled ServerHello with zero-length SCT") } } + +func TestRejectDuplicateExtensions(t *testing.T) { + clientHelloBytes, err := hex.DecodeString("010000440303000000000000000000000000000000000000000000000000000000000000000000000000001c0000000a000800000568656c6c6f0000000a000800000568656c6c6f") + if err != nil { + t.Fatalf("failed to decode test ClientHello: %s", err) + } + var clientHelloCopy clientHelloMsg + if clientHelloCopy.unmarshal(clientHelloBytes) { + t.Error("Unmarshaled ClientHello with duplicate extensions") + } + + serverHelloBytes, err := hex.DecodeString("02000030030300000000000000000000000000000000000000000000000000000000000000000000000000080005000000050000") + if err != nil { + t.Fatalf("failed to decode test ServerHello: %s", err) + } + var serverHelloCopy serverHelloMsg + if serverHelloCopy.unmarshal(serverHelloBytes) { + t.Fatal("Unmarshaled ServerHello with duplicate extensions") + } +} -- cgit v1.2.3-54-g00ecf From b941a10e384e6772792bc9e05e7ebe58e98bc20e Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 19 Apr 2022 12:05:10 -0700 Subject: crypto/x509: use SAN when comparing certs during path building Per RFC 4158 Section 2.4.2, when we are discarding candidate certificates during path building, use the SANs as well as subject and public key when checking whether a certificate is already present in the built path. This supports the case where a certificate in the chain (typically a leaf) has the exact same subject and public key as another certificate in the chain (typically its parent) but has SANs which don't match. Change-Id: I212c234e94a1f6afbe9691e4a3ba257461db3a7e Reviewed-on: https://go-review.googlesource.com/c/go/+/401115 Reviewed-by: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Gopher Robot Reviewed-by: Damien Neil --- src/crypto/x509/verify.go | 58 ++++++++++++++++++++++++++++++++++-------- src/crypto/x509/verify_test.go | 23 +++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 77ad6868fa..a739956cfe 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -7,6 +7,7 @@ package x509 import ( "bytes" "crypto" + "crypto/x509/pkix" "errors" "fmt" "net" @@ -825,6 +826,50 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate return n } +// alreadyInChain checks whether a candidate certificate is present in a chain. +// Rather than doing a direct byte for byte equivalency check, we check if the +// subject, public key, and SAN, if present, are equal. This prevents loops that +// are created by mutual cross-signatures, or other cross-signature bridge +// oddities. +func alreadyInChain(candidate *Certificate, chain []*Certificate) bool { + type pubKeyEqual interface { + Equal(crypto.PublicKey) bool + } + + var candidateSAN *pkix.Extension + for _, ext := range candidate.Extensions { + if ext.Id.Equal(oidExtensionSubjectAltName) { + candidateSAN = &ext + break + } + } + + for _, cert := range chain { + if !bytes.Equal(candidate.RawSubject, cert.RawSubject) { + continue + } + if !candidate.PublicKey.(pubKeyEqual).Equal(cert.PublicKey) { + continue + } + var certSAN *pkix.Extension + for _, ext := range cert.Extensions { + if ext.Id.Equal(oidExtensionSubjectAltName) { + certSAN = &ext + break + } + } + if candidateSAN == nil && certSAN == nil { + return true + } else if candidateSAN == nil || certSAN == nil { + return false + } + if bytes.Equal(candidateSAN.Value, certSAN.Value) { + return true + } + } + return false +} + // maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls // that an invocation of buildChains will (transitively) make. Most chains are // less than 15 certificates long, so this leaves space for multiple chains and @@ -837,18 +882,9 @@ func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, o hintCert *Certificate ) - type pubKeyEqual interface { - Equal(crypto.PublicKey) bool - } - considerCandidate := func(certType int, candidate *Certificate) { - for _, cert := range currentChain { - // If a certificate already appeared in the chain we've built, don't - // reconsider it. This prevents loops, for isntance those created by - // mutual cross-signatures, or other cross-signature bridges oddities. - if bytes.Equal(cert.RawSubject, candidate.RawSubject) && cert.PublicKey.(pubKeyEqual).Equal(candidate.PublicKey) { - return - } + if alreadyInChain(candidate, currentChain) { + return } if sigChecks == nil { diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 1b2cbe34dd..8a7b08ab58 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -2340,6 +2340,29 @@ func TestPathBuilding(t *testing.T) { "CN=leaf -> CN=inter b -> CN=inter c -> CN=root", }, }, + { + // Build a simple two node graph, where the leaf is directly issued from + // the root and both certificates have matching subject and public key, but + // the leaf has SANs. + name: "leaf with same subject, key, as parent but with SAN", + graph: trustGraphDescription{ + Roots: []string{"root"}, + Leaf: "root", + Graph: []trustGraphEdge{ + { + Issuer: "root", + Subject: "root", + Type: leafCertificate, + MutateTemplate: func(c *Certificate) { + c.DNSNames = []string{"localhost"} + }, + }, + }, + }, + expectedChains: []string{ + "CN=root -> CN=root", + }, + }, } for _, tc := range tests { -- cgit v1.2.3-54-g00ecf From 115852077f45141b293727558e61c0804661d328 Mon Sep 17 00:00:00 2001 From: Bryan Mills Date: Thu, 21 Apr 2022 13:22:59 +0000 Subject: Revert "cmd/go/internal/test: wrap os.Stdout always" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts CL 400877. Reason for revert: broke TestScript/test_output_wait and the regression test for #18153 on certain builders. Fixes #52461. Change-Id: I98627ce5e22088b0784be502c459480c41ba353a Reviewed-on: https://go-review.googlesource.com/c/go/+/401494 Reviewed-by: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Gopher Robot Auto-Submit: Bryan Mills Reviewed-by: Michael Pratt --- src/cmd/go/internal/test/test.go | 6 +---- src/cmd/go/testdata/script/test_output_wait.txt | 35 ------------------------- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 src/cmd/go/testdata/script/test_output_wait.txt diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index f2d2290dbb..50e6d5201b 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1261,11 +1261,7 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. return nil } - // The os/exec package treats an *os.File differently to an io.Writer. - // Embed os.Stdout in an io.Writer struct so that we get the same - // behavior regardless of whether we wrap it below. - // See golang.org/issue/24050 - var stdout io.Writer = struct{ io.Writer }{os.Stdout} + var stdout io.Writer = os.Stdout var err error if testJSON { json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp) diff --git a/src/cmd/go/testdata/script/test_output_wait.txt b/src/cmd/go/testdata/script/test_output_wait.txt deleted file mode 100644 index 878b108612..0000000000 --- a/src/cmd/go/testdata/script/test_output_wait.txt +++ /dev/null @@ -1,35 +0,0 @@ -# Wait for test output from sub-processes whether or not the package name is -# provided on the command-line. -go test -v -stdout 'PASS\s+WAIT\s+ok' -go test -v . -stdout 'PASS\s+WAIT\s+ok' - --- go.mod -- -module x - --- x_test.go -- -package x - -import ( - "os" - "os/exec" - "testing" -) - -func TestMain(m *testing.M) { - if os.Getenv("WAIT") == "true" { - os.Stdout.Write([]byte("WAIT\n")) - return - } - m.Run() -} - -func TestWait(t *testing.T) { - cmd := exec.Command(os.Args[0]) - cmd.Env = []string{"WAIT=true"} - cmd.Stdout = os.Stdout - if err := cmd.Start(); err != nil { - t.Fatal(err) - } -} -- cgit v1.2.3-54-g00ecf From b34838913da606087b0f3141891f7d0fb2254eef Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 20 Apr 2022 17:07:14 -0400 Subject: os/exec: set PWD implicitly if Dir is non-empty and Env is nil Fixes #50599. Change-Id: I4e5dbb3972cdf21ede049567bfb98f2c992c5849 Reviewed-on: https://go-review.googlesource.com/c/go/+/401340 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Auto-Submit: Bryan Mills Reviewed-by: Ian Lance Taylor --- api/next/50599.txt | 1 + doc/go1.19.html | 15 +++++ src/os/exec/example_test.go | 15 +++++ src/os/exec/exec.go | 59 +++++++++++++--- src/os/exec/exec_posix_test.go | 149 +++++++++++++++++++++++++++++++++++++++++ src/os/exec/exec_test.go | 20 +++++- 6 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 api/next/50599.txt diff --git a/api/next/50599.txt b/api/next/50599.txt new file mode 100644 index 0000000000..be271ea5e4 --- /dev/null +++ b/api/next/50599.txt @@ -0,0 +1 @@ +pkg os/exec, method (*Cmd) Environ() []string #50599 diff --git a/doc/go1.19.html b/doc/go1.19.html index a813d59cb8..8305decece 100644 --- a/doc/go1.19.html +++ b/doc/go1.19.html @@ -132,6 +132,21 @@ Do not send CLs removing the interior tags from such phrases. +
    os/exec
    +
    +

    + An exec.Cmd with a non-empty Dir and a + nil Env now implicitly sets the PWD environment + variable for the subprocess to match Dir. +

    +

    + The new method (*exec.Cmd).Environ reports the + environment that would be used to run the command, including the + aforementioned PWD variable. +

    +
    +
    +
    runtime

    diff --git a/src/os/exec/example_test.go b/src/os/exec/example_test.go index a66890be69..bb166ceaf4 100644 --- a/src/os/exec/example_test.go +++ b/src/os/exec/example_test.go @@ -144,6 +144,21 @@ func ExampleCmd_CombinedOutput() { fmt.Printf("%s\n", stdoutStderr) } +func ExampleCmd_Environ() { + cmd := exec.Command("pwd") + + // Set Dir before calling cmd.Environ so that it will include an + // updated PWD variable (on platforms where that is used). + cmd.Dir = ".." + cmd.Env = append(cmd.Environ(), "POSIXLY_CORRECT=1") + + out, err := cmd.Output() + if err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n", out) +} + func ExampleCommandContext() { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index 58f8bbf84d..eeca83713b 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -223,13 +223,6 @@ func interfaceEqual(a, b any) bool { return a == b } -func (c *Cmd) envv() ([]string, error) { - if c.Env != nil { - return c.Env, nil - } - return execenv.Default(c.SysProcAttr) -} - func (c *Cmd) argv() []string { if len(c.Args) > 0 { return c.Args @@ -414,7 +407,7 @@ func (c *Cmd) Start() error { } c.childFiles = append(c.childFiles, c.ExtraFiles...) - envv, err := c.envv() + env, err := c.environ() if err != nil { return err } @@ -422,7 +415,7 @@ func (c *Cmd) Start() error { c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ Dir: c.Dir, Files: c.childFiles, - Env: addCriticalEnv(dedupEnv(envv)), + Env: env, Sys: c.SysProcAttr, }) if err != nil { @@ -735,6 +728,54 @@ func minInt(a, b int) int { return b } +// environ returns a best-effort copy of the environment in which the command +// would be run as it is currently configured. If an error occurs in computing +// the environment, it is returned alongside the best-effort copy. +func (c *Cmd) environ() ([]string, error) { + var err error + + env := c.Env + if env == nil { + env, err = execenv.Default(c.SysProcAttr) + if err != nil { + env = os.Environ() + // Note that the non-nil err is preserved despite env being overridden. + } + + if c.Dir != "" { + switch runtime.GOOS { + case "windows", "plan9": + // Windows and Plan 9 do not use the PWD variable, so we don't need to + // keep it accurate. + default: + // On POSIX platforms, PWD represents “an absolute pathname of the + // current working directory.” Since we are changing the working + // directory for the command, we should also update PWD to reflect that. + // + // Unfortunately, we didn't always do that, so (as proposed in + // https://go.dev/issue/50599) to avoid unintended collateral damage we + // only implicitly update PWD when Env is nil. That way, we're much + // less likely to override an intentional change to the variable. + if pwd, absErr := filepath.Abs(c.Dir); absErr == nil { + env = append(env, "PWD="+pwd) + } else if err == nil { + err = absErr + } + } + } + } + + return addCriticalEnv(dedupEnv(env)), err +} + +// Environ returns a copy of the environment in which the command would be run +// as it is currently configured. +func (c *Cmd) Environ() []string { + // Intentionally ignore errors: environ returns a best-effort environment no matter what. + env, _ := c.environ() + return env +} + // dedupEnv returns a copy of env with any duplicates removed, in favor of // later values. // Items not of the normal environment "key=value" form are preserved unchanged. diff --git a/src/os/exec/exec_posix_test.go b/src/os/exec/exec_posix_test.go index ce83a9e4b3..a0880c43ed 100644 --- a/src/os/exec/exec_posix_test.go +++ b/src/os/exec/exec_posix_test.go @@ -7,9 +7,15 @@ package exec_test import ( + "internal/testenv" + "os" + "os/exec" "os/user" + "path/filepath" + "reflect" "runtime" "strconv" + "strings" "syscall" "testing" "time" @@ -86,3 +92,146 @@ func TestWaitid(t *testing.T) { <-ch } + +// https://go.dev/issue/50599: if Env is not set explicitly, setting Dir should +// implicitly update PWD to the correct path, and Environ should list the +// updated value. +func TestImplicitPWD(t *testing.T) { + testenv.MustHaveExec(t) + _, pwdErr := exec.LookPath("pwd") + + t.Parallel() + + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + cases := []struct { + name string + dir string + want string + }{ + {"empty", "", cwd}, + {"dot", ".", cwd}, + {"dotdot", "..", filepath.Dir(cwd)}, + {"PWD", cwd, cwd}, + {"PWDdotdot", cwd + string(filepath.Separator) + "..", filepath.Dir(cwd)}, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + // Note: we're using the actual "pwd" command here (instead of helperCommand) + // because the implementation of helperCommand requires a non-empty Env. + // (We could perhaps refactor helperCommand to use a flag or switch on the + // value of argv[0] instead, but that doesn't seem worth the trouble at + // the moment.) + cmd := exec.Command("pwd") + cmd.Dir = tc.dir + + var pwds []string + for _, kv := range cmd.Environ() { + if strings.HasPrefix(kv, "PWD=") { + pwds = append(pwds, strings.TrimPrefix(kv, "PWD=")) + } + } + + wantPWDs := []string{tc.want} + if tc.dir == "" { + if _, ok := os.LookupEnv("PWD"); !ok { + wantPWDs = nil + } + } + if !reflect.DeepEqual(pwds, wantPWDs) { + t.Errorf("PWD entries in cmd.Environ():\n\t%s\nwant:\n\t%s", strings.Join(pwds, "\n\t"), strings.Join(wantPWDs, "\n\t")) + } + + if pwdErr != nil { + t.Skipf("not running `pwd` because it was not found: %v", pwdErr) + } + cmd.Stderr = new(strings.Builder) + out, err := cmd.Output() + if err != nil { + t.Fatalf("%v:\n%s", err, cmd.Stderr) + } + got := strings.Trim(string(out), "\r\n") + t.Logf("in\n\t%s\n`pwd` reported\n\t%s", tc.dir, got) + if got != tc.want { + t.Errorf("want\n\t%s", tc.want) + } + }) + } +} + +// However, if cmd.Env is set explicitly, setting Dir should not override it. +// (This checks that the implementation for https://go.dev/issue/50599 doesn't +// break existing users who may have explicitly mismatched the PWD variable.) +func TestExplicitPWD(t *testing.T) { + testenv.MustHaveSymlink(t) + + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + link := filepath.Join(t.TempDir(), "link") + if err := os.Symlink(cwd, link); err != nil { + t.Fatal(err) + } + + // Now link is another equally-valid name for cwd. If we set Dir to one and + // PWD to the other, the subprocess should report the PWD version. + cases := []struct { + name string + dir string + pwd string + }{ + {name: "original PWD", pwd: cwd}, + {name: "link PWD", pwd: link}, + {name: "in link with original PWD", dir: link, pwd: cwd}, + {name: "in dir with link PWD", dir: cwd, pwd: link}, + // Ideally we would also like to test what happens if we set PWD to + // something totally bogus (or the empty string), but then we would have no + // idea what output the subprocess should actually produce: cwd itself may + // contain symlinks preserved from the PWD value in the test's environment. + } + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + cmd := helperCommand(t, "pwd") + // This is intentionally opposite to the usual order of setting cmd.Dir + // and then calling cmd.Environ. Here, we *want* PWD not to match cmd.Dir, + // so we don't care whether cmd.Dir is reflected in cmd.Environ. + cmd.Env = append(cmd.Environ(), "PWD="+tc.pwd) + cmd.Dir = tc.dir + + var pwds []string + for _, kv := range cmd.Environ() { + if strings.HasPrefix(kv, "PWD=") { + pwds = append(pwds, strings.TrimPrefix(kv, "PWD=")) + } + } + + wantPWDs := []string{tc.pwd} + if !reflect.DeepEqual(pwds, wantPWDs) { + t.Errorf("PWD entries in cmd.Environ():\n\t%s\nwant:\n\t%s", strings.Join(pwds, "\n\t"), strings.Join(wantPWDs, "\n\t")) + } + + cmd.Stderr = new(strings.Builder) + out, err := cmd.Output() + if err != nil { + t.Fatalf("%v:\n%s", err, cmd.Stderr) + } + got := strings.Trim(string(out), "\r\n") + t.Logf("in\n\t%s\nwith PWD=%s\nsubprocess os.Getwd() reported\n\t%s", tc.dir, tc.pwd, got) + if got != tc.pwd { + t.Errorf("want\n\t%s", tc.pwd) + } + }) + } +} diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 73aa35f1ae..f90066cea3 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -57,12 +57,20 @@ func init() { func helperCommandContext(t *testing.T, ctx context.Context, s ...string) (cmd *exec.Cmd) { testenv.MustHaveExec(t) + // Use os.Executable instead of os.Args[0] in case the caller modifies + // cmd.Dir: if the test binary is invoked like "./exec.test", it should + // not fail spuriously. + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + cs := []string{"-test.run=TestHelperProcess", "--"} cs = append(cs, s...) if ctx != nil { - cmd = exec.CommandContext(ctx, os.Args[0], cs...) + cmd = exec.CommandContext(ctx, exe, cs...) } else { - cmd = exec.Command(os.Args[0], cs...) + cmd = exec.Command(exe, cs...) } cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") return cmd @@ -831,6 +839,14 @@ func TestHelperProcess(*testing.T) { } pipe.Close() os.Exit(0) + case "pwd": + pwd, err := os.Getwd() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Println(pwd) + os.Exit(0) default: fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) os.Exit(2) -- cgit v1.2.3-54-g00ecf From c2d436dcfad64d5cc301cf05d446f7a93c19133e Mon Sep 17 00:00:00 2001 From: zhangyunhao Date: Tue, 19 Apr 2022 14:44:03 +0800 Subject: hash/maphash: use fastrand64 in MakeSeed Change-Id: I5ccbcea4c53658136b25ca608faec19eeec2e908 Reviewed-on: https://go-review.googlesource.com/c/go/+/400915 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Run-TryBot: Wayne Zuo TryBot-Result: Gopher Robot --- src/hash/maphash/maphash.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/hash/maphash/maphash.go b/src/hash/maphash/maphash.go index 783690ea00..dfacd021db 100644 --- a/src/hash/maphash/maphash.go +++ b/src/hash/maphash/maphash.go @@ -252,21 +252,20 @@ func (h *Hash) Sum64() uint64 { // MakeSeed returns a new random seed. func MakeSeed() Seed { - var s1, s2 uint64 + var s uint64 for { - s1 = uint64(runtime_fastrand()) - s2 = uint64(runtime_fastrand()) + s = runtime_fastrand64() // We use seed 0 to indicate an uninitialized seed/hash, // so keep trying until we get a non-zero seed. - if s1|s2 != 0 { + if s != 0 { break } } - return Seed{s: s1<<32 + s2} + return Seed{s: s} } -//go:linkname runtime_fastrand runtime.fastrand -func runtime_fastrand() uint32 +//go:linkname runtime_fastrand64 runtime.fastrand64 +func runtime_fastrand64() uint64 func rthash(ptr *byte, len int, seed uint64) uint64 { if len == 0 { -- cgit v1.2.3-54-g00ecf From 01b8f5e8821eac0e3456d6200b351629fd3752f4 Mon Sep 17 00:00:00 2001 From: zhangyunhao Date: Tue, 19 Apr 2022 16:38:04 +0800 Subject: runtime: use fastrand64 in mapiterinit Change-Id: I5698c7576a0f39ae62de7bea64286ac8e578d421 Reviewed-on: https://go-review.googlesource.com/c/go/+/400916 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Run-TryBot: Wayne Zuo TryBot-Result: Gopher Robot --- src/runtime/map.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/runtime/map.go b/src/runtime/map.go index e91b25eaec..2e513e2d52 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -842,9 +842,11 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { } // decide where to start - r := uintptr(fastrand()) + var r uintptr if h.B > 31-bucketCntBits { - r += uintptr(fastrand()) << 31 + r = uintptr(fastrand64()) + } else { + r = uintptr(fastrand()) } it.startBucket = r & bucketMask(h.B) it.offset = uint8(r >> h.B & (bucketCnt - 1)) -- cgit v1.2.3-54-g00ecf From a4bbcd4b1fc9dd40e0f86416d37bdd9e6d430f3f Mon Sep 17 00:00:00 2001 From: zhangyunhao Date: Tue, 19 Apr 2022 14:20:29 +0800 Subject: net: use fastrand64 in randInt Change-Id: If3d8391d81e8de869dbb3c857f0570817e8aa440 Reviewed-on: https://go-review.googlesource.com/c/go/+/400914 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Run-TryBot: Wayne Zuo TryBot-Result: Gopher Robot --- src/net/dnsclient.go | 7 ++----- src/runtime/stubs.go | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go index a779c37e53..b609dbd468 100644 --- a/src/net/dnsclient.go +++ b/src/net/dnsclient.go @@ -13,13 +13,10 @@ import ( ) // provided by runtime -func fastrand() uint32 +func fastrandu() uint func randInt() int { - x, y := fastrand(), fastrand() // 32-bit halves - u := uint(x)<<31 ^ uint(int32(y)) // full uint, even on 64-bit systems; avoid 32-bit shift on 32-bit systems - i := int(u >> 1) // clear sign bit, even on 32-bit systems - return i + return int(fastrandu() >> 1) // clear sign bit } func randIntn(n int) int { diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index ca0cd1ba25..929f8fadca 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -199,8 +199,8 @@ func fastrandu() uint { //go:linkname sync_fastrandn sync.fastrandn func sync_fastrandn(n uint32) uint32 { return fastrandn(n) } -//go:linkname net_fastrand net.fastrand -func net_fastrand() uint32 { return fastrand() } +//go:linkname net_fastrandu net.fastrandu +func net_fastrandu() uint { return fastrandu() } //go:linkname os_fastrand os.fastrand func os_fastrand() uint32 { return fastrand() } -- cgit v1.2.3-54-g00ecf From 824b0a34b7b4fbda1de9f5dbb39c3b33458bc541 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 21 Apr 2022 11:17:16 -0400 Subject: cmd/go: replace some calls to base.AppendPWD with cmd.Environ With #50599 implemented, base.AppendPWD is redundant if cmd.Env would otherwise be nil, and calls to os.Environ followed by base.AppendPWD can be replaced by a simpler call to cmd.Environ. Updates #50599. Change-Id: I94a22e2a4cc8e83c815ac41702ea0b1ee5034ecc Reviewed-on: https://go-review.googlesource.com/c/go/+/401534 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/vcs/vcs.go | 2 -- src/cmd/go/internal/work/exec.go | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 77208ab762..7dbcfb7cc4 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -22,7 +22,6 @@ import ( "sync" "time" - "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/search" "cmd/go/internal/str" @@ -657,7 +656,6 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ cmd := exec.Command(v.Cmd, args...) cmd.Dir = dir - cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir) if cfg.BuildX { fmt.Fprintf(os.Stderr, "cd %s\n", dir) fmt.Fprintf(os.Stderr, "%s %s\n", v.Cmd, strings.Join(args, " ")) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index f0e6c80029..0b8e5d2330 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2116,11 +2116,10 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([ cmd.Stderr = &buf cleanup := passLongArgsInResponseFiles(cmd) defer cleanup() - cmd.Env = os.Environ() if dir != "." { cmd.Dir = dir - cmd.Env = base.AppendPWD(cmd.Env, dir) } + cmd.Env = cmd.Environ() // Pre-allocate with correct PWD. // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools. // It doesn't really matter if -toolexec isn't being used. @@ -2609,8 +2608,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool { } cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) cmd.Dir = b.WorkDir - cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir) - cmd.Env = append(cmd.Env, "LC_ALL=C") + cmd.Env = append(cmd.Environ(), "LC_ALL=C") out, _ := cmd.CombinedOutput() // GCC says "unrecognized command line option". // clang says "unknown argument". -- cgit v1.2.3-54-g00ecf From 9de57244e1708cbdac5b8d53e5cf7eea788f3f33 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 21 Apr 2022 11:19:56 -0400 Subject: go/build: replace a call to os.Environ with (*exec.Cmd).Environ This is a code simplification using the new API added in #50599. Change-Id: Icb9628bcd0daa3dc2d653e9654b38099730137d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/401535 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/go/build/build.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/go/build/build.go b/src/go/build/build.go index 17fef051b3..bfa9cd60fb 100644 --- a/src/go/build/build.go +++ b/src/go/build/build.go @@ -1185,20 +1185,13 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) if ctxt.CgoEnabled { cgo = "1" } - cmd.Env = append(os.Environ(), + cmd.Env = append(cmd.Environ(), "GOOS="+ctxt.GOOS, "GOARCH="+ctxt.GOARCH, "GOROOT="+ctxt.GOROOT, "GOPATH="+ctxt.GOPATH, "CGO_ENABLED="+cgo, ) - if cmd.Dir != "" { - // If possible, set PWD: if an error occurs and PWD includes a symlink, we - // want the error to refer to Dir, not some other name for it. - if abs, err := filepath.Abs(cmd.Dir); err == nil { - cmd.Env = append(cmd.Env, "PWD="+abs) - } - } if err := cmd.Run(); err != nil { return fmt.Errorf("go/build: go list %s: %v\n%s\n", path, err, stderr.String()) -- cgit v1.2.3-54-g00ecf From e25a5ce120673835a7e6c92bf0d88f44a61e9079 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 25 Feb 2022 14:31:32 -0500 Subject: test: rename live_syscall.go to live_uintptrkeepalive.go CL 388095 will change this file significantly. Move it preemptively to ensure git tracks the move properly. For #51087 Change-Id: I1408aecf8675723041b64e54cf44cdec38cc655c Reviewed-on: https://go-review.googlesource.com/c/go/+/388094 Run-TryBot: Michael Pratt Reviewed-by: Matthew Dempsky Reviewed-by: David Chase TryBot-Result: Gopher Robot --- test/live_syscall.go | 40 ---------------------------------------- test/live_uintptrkeepalive.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) delete mode 100644 test/live_syscall.go create mode 100644 test/live_uintptrkeepalive.go diff --git a/test/live_syscall.go b/test/live_syscall.go deleted file mode 100644 index b920ff68aa..0000000000 --- a/test/live_syscall.go +++ /dev/null @@ -1,40 +0,0 @@ -// errorcheck -0 -m -live - -// +build !windows,!js - -// Copyright 2015 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. - -// Test escape analysis and liveness inferred for syscall.Syscall-like functions. - -package p - -import ( - "syscall" - "unsafe" -) - -func f(uintptr) // ERROR "assuming arg#1 is unsafe uintptr" - -func g() { // ERROR "can inline g" - var t int - f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" -} - -func h() { // ERROR "can inline h" - var v int - syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" -} - -func i() { // ERROR "can inline i" - var t int - p := unsafe.Pointer(&t) - f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" -} - -func j() { // ERROR "can inline j" - var v int - p := unsafe.Pointer(&v) - syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" -} diff --git a/test/live_uintptrkeepalive.go b/test/live_uintptrkeepalive.go new file mode 100644 index 0000000000..b920ff68aa --- /dev/null +++ b/test/live_uintptrkeepalive.go @@ -0,0 +1,40 @@ +// errorcheck -0 -m -live + +// +build !windows,!js + +// Copyright 2015 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. + +// Test escape analysis and liveness inferred for syscall.Syscall-like functions. + +package p + +import ( + "syscall" + "unsafe" +) + +func f(uintptr) // ERROR "assuming arg#1 is unsafe uintptr" + +func g() { // ERROR "can inline g" + var t int + f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} + +func h() { // ERROR "can inline h" + var v int + syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} + +func i() { // ERROR "can inline i" + var t int + p := unsafe.Pointer(&t) + f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} + +func j() { // ERROR "can inline j" + var v int + p := unsafe.Pointer(&v) + syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} -- cgit v1.2.3-54-g00ecf From 342b495301bbd8b75c2721212a08ce41e3f82265 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 25 Feb 2022 14:21:25 -0500 Subject: cmd/compile: add //go:uintptrkeepalive This CL exports the existing ir.UintptrKeepAlive via the new directive //go:uintptrkeepalive. This makes the compiler insert KeepAlives for pointers converted to uintptr in calls, keeping them alive for the duration of the call. //go:uintptrkeepalive requires //go:nosplit, as stack growth can't handle these arguments (it cannot know which are pointers). We currently check this on the immediate function, but the actual restriction applies to all transitive calls. The existing //go:uintptrescapes is an extension of //go:uintptrkeepalive which forces pointers to escape to the heap, thus eliminating the stack growth issue. This pragma is limited to the standard library. For #51087 Change-Id: If9a19d484d3561b4219e5539b70c11a3cc09391e Reviewed-on: https://go-review.googlesource.com/c/go/+/388095 Run-TryBot: Michael Pratt Reviewed-by: Matthew Dempsky TryBot-Result: Gopher Robot --- src/cmd/compile/doc.go | 12 +++++---- src/cmd/compile/internal/escape/escape.go | 2 -- src/cmd/compile/internal/inline/inl.go | 11 +++++++++ src/cmd/compile/internal/ir/node.go | 2 +- src/cmd/compile/internal/noder/decl.go | 22 +++++++++++++++-- src/cmd/compile/internal/noder/lex.go | 19 ++++++-------- src/cmd/compile/internal/noder/noder.go | 3 +++ src/cmd/compile/internal/noder/writer.go | 16 ++++++++++++ src/runtime/HACKING.md | 19 ++++++++++++++ test/live_uintptrkeepalive.go | 41 ++++++++++++++++++++++++------- test/uintptrkeepalive.go | 11 +++++++++ 11 files changed, 127 insertions(+), 31 deletions(-) create mode 100644 test/uintptrkeepalive.go diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go index ef7fa86749..b8862f62cf 100644 --- a/src/cmd/compile/doc.go +++ b/src/cmd/compile/doc.go @@ -219,11 +219,13 @@ calling the function. //go:uintptrescapes The //go:uintptrescapes directive must be followed by a function declaration. -It specifies that the function's uintptr arguments may be pointer values -that have been converted to uintptr and must be treated as such by the -garbage collector. The conversion from pointer to uintptr must appear in -the argument list of any call to this function. This directive is necessary -for some low-level system call implementations and should be avoided otherwise. +It specifies that the function's uintptr arguments may be pointer values that +have been converted to uintptr and must be on the heap and kept alive for the +duration of the call, even though from the types alone it would appear that the +object is no longer needed during the call. The conversion from pointer to +uintptr must appear in the argument list of any call to this function. This +directive is necessary for some low-level system call implementations and +should be avoided otherwise. //go:noinline diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 4408a531ec..05fbe58bbc 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -422,8 +422,6 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { } if fn.Pragma&ir.UintptrEscapes != 0 { - fn.Pragma |= ir.UintptrKeepAlive - if f.Type.IsUintptr() { if diagnose { base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 8c2ea49c8f..486a6ad319 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -120,6 +120,17 @@ func CanInline(fn *ir.Func) { return } + // If marked as "go:uintptrkeepalive", don't inline, since the + // keep alive information is lost during inlining. + // + // TODO(prattmic): This is handled on calls during escape analysis, + // which is after inlining. Move prior to inlining so the keep-alive is + // maintained after inlining. + if fn.Pragma&ir.UintptrKeepAlive != 0 { + reason = "marked as having a keep-alive uintptr argument" + return + } + // If marked as "go:uintptrescapes", don't inline, since the // escape information is lost during inlining. if fn.Pragma&ir.UintptrEscapes != 0 { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 9ccb8e3c30..0d91d17344 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -459,7 +459,7 @@ const ( Noinline // func should not be inlined NoCheckPtr // func should not be instrumented by checkptr CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all - UintptrKeepAlive // pointers converted to uintptr must be kept alive (compiler internal only) + UintptrKeepAlive // pointers converted to uintptr must be kept alive UintptrEscapes // pointers converted to uintptr escape // Runtime-only func pragmas. diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index f985648c66..91a90d9e09 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -125,8 +125,26 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } } - if decl.Body != nil && fn.Pragma&ir.Noescape != 0 { - base.ErrorfAt(fn.Pos(), "can only use //go:noescape with external func implementations") + if decl.Body != nil { + if fn.Pragma&ir.Noescape != 0 { + base.ErrorfAt(fn.Pos(), "can only use //go:noescape with external func implementations") + } + if (fn.Pragma&ir.UintptrKeepAlive != 0 && fn.Pragma&ir.UintptrEscapes == 0) && fn.Pragma&ir.Nosplit == 0 { + // Stack growth can't handle uintptr arguments that may + // be pointers (as we don't know which are pointers + // when creating the stack map). Thus uintptrkeepalive + // functions (and all transitive callees) must be + // nosplit. + // + // N.B. uintptrescapes implies uintptrkeepalive but it + // is OK since the arguments must escape to the heap. + // + // TODO(prattmic): Add recursive nosplit check of callees. + // TODO(prattmic): Functions with no body (i.e., + // assembly) must also be nosplit, but we can't check + // that here. + base.ErrorfAt(fn.Pos(), "go:uintptrkeepalive requires go:nosplit") + } } if decl.Name.Value == "init" && decl.Recv == nil { diff --git a/src/cmd/compile/internal/noder/lex.go b/src/cmd/compile/internal/noder/lex.go index 66a56a50ec..cef0f082ca 100644 --- a/src/cmd/compile/internal/noder/lex.go +++ b/src/cmd/compile/internal/noder/lex.go @@ -30,6 +30,7 @@ const ( ir.NoCheckPtr | ir.RegisterParams | // TODO(register args) remove after register abi is working ir.CgoUnsafeArgs | + ir.UintptrKeepAlive | ir.UintptrEscapes | ir.Systemstack | ir.Nowritebarrier | @@ -67,19 +68,13 @@ func pragmaFlag(verb string) ir.PragmaFlag { return ir.Yeswritebarrierrec case "go:cgo_unsafe_args": return ir.CgoUnsafeArgs | ir.NoCheckPtr // implies NoCheckPtr (see #34968) + case "go:uintptrkeepalive": + return ir.UintptrKeepAlive case "go:uintptrescapes": - // For the next function declared in the file - // any uintptr arguments may be pointer values - // converted to uintptr. This directive - // ensures that the referenced allocated - // object, if any, is retained and not moved - // until the call completes, even though from - // the types alone it would appear that the - // object is no longer needed during the - // call. The conversion to uintptr must appear - // in the argument list. - // Used in syscall/dll_windows.go. - return ir.UintptrEscapes + // This directive extends //go:uintptrkeepalive by forcing + // uintptr arguments to escape to the heap, which makes stack + // growth safe. + return ir.UintptrEscapes | ir.UintptrKeepAlive // implies UintptrKeepAlive case "go:registerparams": // TODO(register args) remove after register abi is working return ir.RegisterParams case "go:notinheap": diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index cc5610acda..9a42b5afd1 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -340,6 +340,9 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 { p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)}) } + if flag == ir.UintptrKeepAlive && !base.Flag.Std { + p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is only allowed in the standard library", verb)}) + } if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std { p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)}) } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index c5c346b784..0fb162d381 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -742,6 +742,22 @@ func (w *writer) funcExt(obj *types2.Func) { if pragma&ir.Noescape != 0 { w.p.errorf(decl, "can only use //go:noescape with external func implementations") } + if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 { + // Stack growth can't handle uintptr arguments that may + // be pointers (as we don't know which are pointers + // when creating the stack map). Thus uintptrkeepalive + // functions (and all transitive callees) must be + // nosplit. + // + // N.B. uintptrescapes implies uintptrkeepalive but it + // is OK since the arguments must escape to the heap. + // + // TODO(prattmic): Add recursive nosplit check of callees. + // TODO(prattmic): Functions with no body (i.e., + // assembly) must also be nosplit, but we can't check + // that here. + w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit") + } } else { if base.Flag.Complete || decl.Name.Value == "init" { // Linknamed functions are allowed to have no body. Hopefully diff --git a/src/runtime/HACKING.md b/src/runtime/HACKING.md index fbf22eeb44..61755241c5 100644 --- a/src/runtime/HACKING.md +++ b/src/runtime/HACKING.md @@ -277,6 +277,25 @@ functions that release the P or may run without a P and Since these are function-level annotations, code that releases or acquires a P may need to be split across two functions. +go:uintptrkeepalive +------------------- + +The //go:uintptrkeepalive directive must be followed by a function declaration. + +It specifies that the function's uintptr arguments may be pointer values that +have been converted to uintptr and must be kept alive for the duration of the +call, even though from the types alone it would appear that the object is no +longer needed during the call. + +This directive is similar to //go:uintptrescapes, but it does not force +arguments to escape. Since stack growth does not understand these arguments, +this directive must be used with //go:nosplit (in the marked function and all +transitive calls) to prevent stack growth. + +The conversion from pointer to uintptr must appear in the argument list of any +call to this function. This directive is used for some low-level system call +implementations. + go:notinheap ------------ diff --git a/test/live_uintptrkeepalive.go b/test/live_uintptrkeepalive.go index b920ff68aa..10c4c7505b 100644 --- a/test/live_uintptrkeepalive.go +++ b/test/live_uintptrkeepalive.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -live +// errorcheck -0 -m -live -std // +build !windows,!js @@ -6,7 +6,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Test escape analysis and liveness inferred for syscall.Syscall-like functions. +// Test escape analysis and liveness inferred for uintptrkeepalive functions. +// +// This behavior is enabled automatically for function declarations with no +// bodies (assembly, linkname), as well as explicitly on complete functions +// with //go:uintptrkeepalive. +// +// This is most important for syscall.Syscall (and similiar functions), so we +// test it explicitly. package p @@ -15,25 +22,41 @@ import ( "unsafe" ) -func f(uintptr) // ERROR "assuming arg#1 is unsafe uintptr" +func implicit(uintptr) // ERROR "assuming arg#1 is unsafe uintptr" -func g() { // ERROR "can inline g" +//go:uintptrkeepalive +//go:nosplit +func explicit(uintptr) { +} + +func autotmpImplicit() { // ERROR "can inline autotmpImplicit" + var t int + implicit(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to implicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} + +func autotmpExplicit() { // ERROR "can inline autotmpExplicit" var t int - f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" + explicit(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to explicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" } -func h() { // ERROR "can inline h" +func autotmpSyscall() { // ERROR "can inline autotmpSyscall" var v int syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" } -func i() { // ERROR "can inline i" +func localImplicit() { // ERROR "can inline localImplicit" + var t int + p := unsafe.Pointer(&t) + implicit(uintptr(p)) // ERROR "live at call to implicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" +} + +func localExplicit() { // ERROR "can inline localExplicit" var t int p := unsafe.Pointer(&t) - f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" + explicit(uintptr(p)) // ERROR "live at call to explicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" } -func j() { // ERROR "can inline j" +func localSyscall() { // ERROR "can inline localSyscall" var v int p := unsafe.Pointer(&v) syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" diff --git a/test/uintptrkeepalive.go b/test/uintptrkeepalive.go new file mode 100644 index 0000000000..97834dcd1a --- /dev/null +++ b/test/uintptrkeepalive.go @@ -0,0 +1,11 @@ +// errorcheck -std + +// Copyright 2022 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 p + +//go:uintptrkeepalive +func missingNosplit(uintptr) { // ERROR "go:uintptrkeepalive requires go:nosplit" +} -- cgit v1.2.3-54-g00ecf From 1de1c0d10df18f4fda46aff82aadd9edfba2b751 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 28 Feb 2022 13:41:33 -0500 Subject: syscall: move Syscall declarations to OS files Future CLs will be changing the provenance of these functions. Move the declarations to the individual OS files now so that future CLs can change only 1 OS at a time rather than changing all at once. For #51087 Change-Id: I5e1bca71e670263d8c0faa586c1b6b4de1a114b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/388474 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/syscall/syscall_aix.go | 5 +++++ src/syscall/syscall_darwin.go | 5 +++++ src/syscall/syscall_dragonfly.go | 5 +++++ src/syscall/syscall_freebsd.go | 5 +++++ src/syscall/syscall_linux.go | 5 +++++ src/syscall/syscall_netbsd.go | 8 ++++++-- src/syscall/syscall_openbsd.go | 8 ++++++-- src/syscall/syscall_solaris.go | 5 +++++ src/syscall/syscall_unix.go | 5 ----- 9 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index a2f8c78438..693424165e 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -15,6 +15,11 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + // Implemented in runtime/syscall_aix.go. func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go index 2e5387a6d9..663bd98c10 100644 --- a/src/syscall/syscall_darwin.go +++ b/src/syscall/syscall_darwin.go @@ -17,6 +17,11 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + var dupTrampoline = abi.FuncPCABI0(libc_dup2_trampoline) type SockaddrDatalink struct { diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go index d8edca9961..3628895ef9 100644 --- a/src/syscall/syscall_dragonfly.go +++ b/src/syscall/syscall_dragonfly.go @@ -17,6 +17,11 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + const _SYS_DUP3 = 0 // See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h diff --git a/src/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go index 8494b21e5b..0637215f89 100644 --- a/src/syscall/syscall_freebsd.go +++ b/src/syscall/syscall_freebsd.go @@ -17,6 +17,11 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + const ( _SYS_FSTAT_FREEBSD12 = 551 // { int fstat(int fd, _Out_ struct stat *sb); } _SYS_FSTATAT_FREEBSD12 = 552 // { int fstatat(int fd, _In_z_ char *path, _Out_ struct stat *buf, int flag); } diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 74322caea1..a10bfbb0c9 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -16,6 +16,11 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go index 9ccb66c083..07afa072fc 100644 --- a/src/syscall/syscall_netbsd.go +++ b/src/syscall/syscall_netbsd.go @@ -14,6 +14,12 @@ package syscall import "unsafe" +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + const _SYS_DUP3 = SYS_DUP3 type SockaddrDatalink struct { @@ -28,8 +34,6 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } -func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) - func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) { var olen uintptr diff --git a/src/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go index 1d82351084..19cf1f4985 100644 --- a/src/syscall/syscall_openbsd.go +++ b/src/syscall/syscall_openbsd.go @@ -14,6 +14,12 @@ package syscall import "unsafe" +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + type SockaddrDatalink struct { Len uint8 Family uint8 @@ -26,8 +32,6 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } -func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) - func nametomib(name string) (mib []_C_int, err error) { // Perform lookup via a binary search left := 0 diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index 37ce5c9e3c..e591ae6671 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -14,6 +14,11 @@ package syscall import "unsafe" +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC // Implemented in asm_solaris_amd64.s. diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index e12f024fe7..cf0e238e2f 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -28,11 +28,6 @@ const ( netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4 ) -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. func clen(n []byte) int { if i := bytealg.IndexByte(n, 0); i != -1 { -- cgit v1.2.3-54-g00ecf From 15602e88658a9dd43cec4220e01ef408d273f028 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 24 Feb 2022 16:35:06 -0500 Subject: runtime/internal/syscall, syscall: replace RawSyscall6 with runtime implementation on linux For #51087 Change-Id: I75a1bdeb5089454595f5ca04765a9c6e45cf9bd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/388475 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/runtime/internal/syscall/syscall_linux.go | 27 ++++++++++++++++++++++++++ src/syscall/asm_linux_386.s | 23 ---------------------- src/syscall/asm_linux_amd64.s | 23 ---------------------- src/syscall/asm_linux_arm.s | 28 --------------------------- src/syscall/asm_linux_arm64.s | 23 ---------------------- src/syscall/asm_linux_mips64x.s | 21 -------------------- src/syscall/asm_linux_mipsx.s | 23 ---------------------- src/syscall/asm_linux_ppc64x.s | 21 -------------------- src/syscall/asm_linux_riscv64.s | 24 ----------------------- src/syscall/asm_linux_s390x.s | 23 ---------------------- src/syscall/syscall_linux.go | 6 ++++++ 11 files changed, 33 insertions(+), 209 deletions(-) diff --git a/src/runtime/internal/syscall/syscall_linux.go b/src/runtime/internal/syscall/syscall_linux.go index 06d5f21e7c..7f268e8fba 100644 --- a/src/runtime/internal/syscall/syscall_linux.go +++ b/src/runtime/internal/syscall/syscall_linux.go @@ -5,8 +5,35 @@ // Package syscall provides the syscall primitives required for the runtime. package syscall +import ( + _ "unsafe" // for go:linkname +) + // TODO(https://go.dev/issue/51087): This package is incomplete and currently // only contains very minimal support for Linux. // Syscall6 calls system call number 'num' with arguments a1-6. func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) + +// syscall_RawSyscall6 is a push linkname to export Syscall6 as +// syscall.RawSyscall6. +// +// //go:uintptrkeepalive because the uintptr argument may be converted pointers +// that need to be kept alive in the caller (this is implied for Syscall6 since +// it has no body). +// +// //go:nosplit because stack copying does not account for uintptrkeepalive, so +// the stack must not grow. Stack copying cannot blindly assume that all +// uintptr arguments are pointers, because some values may look like pointers, +// but not really be pointers, and adjusting their value would break the call. +// +// This is a separate wrapper because we can't export one function as two +// names. The assembly implementations name themselves Syscall6 would not be +// affected by a linkname. +// +//go:uintptrkeepalive +//go:nosplit +//go:linkname syscall_RawSyscall6 syscall.RawSyscall6 +func syscall_RawSyscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) { + return Syscall6(num, a1, a2, a3, a4, a5, a6) +} diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index 1c69083118..a2b5efb2db 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -87,29 +87,6 @@ ok1: MOVL $0, err+24(FP) RET -// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - MOVL trap+0(FP), AX // syscall entry - MOVL a1+4(FP), BX - MOVL a2+8(FP), CX - MOVL a3+12(FP), DX - MOVL a4+16(FP), SI - MOVL a5+20(FP), DI - MOVL a6+24(FP), BP - INVOKE_SYSCALL - CMPL AX, $0xfffff001 - JLS ok2 - MOVL $-1, r1+28(FP) - MOVL $0, r2+32(FP) - NEGL AX - MOVL AX, err+36(FP) - RET -ok2: - MOVL AX, r1+28(FP) - MOVL DX, r2+32(FP) - MOVL $0, err+36(FP) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVL trap+0(FP), AX // syscall entry diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index 0b55a30fa0..a98125903a 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -84,29 +84,6 @@ ok1: MOVQ $0, err+48(FP) RET -// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOVQ a1+8(FP), DI - MOVQ a2+16(FP), SI - MOVQ a3+24(FP), DX - MOVQ a4+32(FP), R10 - MOVQ a5+40(FP), R8 - MOVQ a6+48(FP), R9 - MOVQ trap+0(FP), AX // syscall entry - SYSCALL - CMPQ AX, $0xfffffffffffff001 - JLS ok2 - MOVQ $-1, r1+56(FP) - MOVQ $0, r2+64(FP) - NEGQ AX - MOVQ AX, err+72(FP) - RET -ok2: - MOVQ AX, r1+56(FP) - MOVQ DX, r2+64(FP) - MOVQ $0, err+72(FP) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVQ a1+8(FP), DI diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 6bb4df81a0..50103172ba 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -70,34 +70,6 @@ ok6: BL runtime·exitsyscall(SB) RET -// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); -// Actually RawSyscall5 but the rest of the code expects it to be named RawSyscall6. -TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 - MOVW trap+0(FP), R7 // syscall entry - MOVW a1+4(FP), R0 - MOVW a2+8(FP), R1 - MOVW a3+12(FP), R2 - MOVW a4+16(FP), R3 - MOVW a5+20(FP), R4 - MOVW a6+24(FP), R5 - SWI $0 - MOVW $0xfffff001, R6 - CMP R6, R0 - BLS ok2 - MOVW $-1, R1 - MOVW R1, r1+28(FP) - MOVW $0, R2 - MOVW R2, r2+32(FP) - RSB $0, R0, R0 - MOVW R0, err+36(FP) - RET -ok2: - MOVW R0, r1+28(FP) - MOVW R1, r2+32(FP) - MOVW $0, R0 - MOVW R0, err+36(FP) - RET - #define SYS__LLSEEK 140 /* from zsysnum_linux_arm.go */ // func seek(fd int, offset int64, whence int) (newoffset int64, errno int) // Implemented in assembly to avoid allocation when diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index 6c50fa9d7c..c9c6bfab09 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -80,29 +80,6 @@ ok: MOVD ZR, err+48(FP) // errno RET -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOVD a1+8(FP), R0 - MOVD a2+16(FP), R1 - MOVD a3+24(FP), R2 - MOVD a4+32(FP), R3 - MOVD a5+40(FP), R4 - MOVD a6+48(FP), R5 - MOVD trap+0(FP), R8 // syscall entry - SVC - CMN $4095, R0 - BCC ok - MOVD $-1, R4 - MOVD R4, r1+56(FP) // r1 - MOVD ZR, r2+64(FP) // r2 - NEG R0, R0 - MOVD R0, err+72(FP) // errno - RET -ok: - MOVD R0, r1+56(FP) // r1 - MOVD R1, r2+64(FP) // r2 - MOVD ZR, err+72(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index a75d0f7a2a..bc2f72c965 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -80,27 +80,6 @@ ok1: MOVV R0, err+48(FP) // errno RET -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOVV a1+8(FP), R4 - MOVV a2+16(FP), R5 - MOVV a3+24(FP), R6 - MOVV a4+32(FP), R7 - MOVV a5+40(FP), R8 - MOVV a6+48(FP), R9 - MOVV trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok2 - MOVV $-1, R1 - MOVV R1, r1+56(FP) // r1 - MOVV R0, r2+64(FP) // r2 - MOVV R2, err+72(FP) // errno - RET -ok2: - MOVV R2, r1+56(FP) // r1 - MOVV R3, r2+64(FP) // r2 - MOVV R0, err+72(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 04f90f6edf..04fad404a4 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -115,29 +115,6 @@ ok1: MOVW R0, err+24(FP) // errno RET -TEXT ·RawSyscall6(SB),NOSPLIT,$20-40 - MOVW a1+4(FP), R4 - MOVW a2+8(FP), R5 - MOVW a3+12(FP), R6 - MOVW a4+16(FP), R7 - MOVW a5+20(FP), R8 - MOVW a6+24(FP), R9 - MOVW R8, 16(R29) - MOVW R9, 20(R29) - MOVW trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok2 - MOVW $-1, R1 - MOVW R1, r1+28(FP) // r1 - MOVW R0, r2+32(FP) // r2 - MOVW R2, err+36(FP) // errno - RET -ok2: - MOVW R2, r1+28(FP) // r1 - MOVW R3, r2+32(FP) // r2 - MOVW R0, err+36(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVW a1+4(FP), R4 diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index bf701e5291..4c9c383ff0 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -80,27 +80,6 @@ ok1: MOVD R0, err+48(FP) // errno RET -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOVD a1+8(FP), R3 - MOVD a2+16(FP), R4 - MOVD a3+24(FP), R5 - MOVD a4+32(FP), R6 - MOVD a5+40(FP), R7 - MOVD a6+48(FP), R8 - MOVD trap+0(FP), R9 // syscall entry - SYSCALL R9 - BVC ok2 - MOVD $-1, R4 - MOVD R4, r1+56(FP) // r1 - MOVD R0, r2+64(FP) // r2 - MOVD R3, err+72(FP) // errno - RET -ok2: - MOVD R3, r1+56(FP) // r1 - MOVD R0, r2+64(FP) // r2 - MOVD R0, err+72(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index f172dd3d9b..c7e1003997 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -80,30 +80,6 @@ err: MOV A0, err+48(FP) // errno RET -// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOV a1+8(FP), A0 - MOV a2+16(FP), A1 - MOV a3+24(FP), A2 - MOV a4+32(FP), A3 - MOV a5+40(FP), A4 - MOV a6+48(FP), A5 - MOV trap+0(FP), A7 // syscall entry - ECALL - MOV $-4096, T0 - BLTU T0, A0, err - MOV A0, r1+56(FP) // r1 - MOV A1, r2+64(FP) // r2 - MOV ZERO, err+72(FP) // errno - RET -err: - MOV $-1, T0 - MOV T0, r1+56(FP) // r1 - MOV ZERO, r2+64(FP) // r2 - SUB A0, ZERO, A0 - MOV A0, err+72(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOV a1+8(FP), A0 diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 86a5c51ee2..3fbda38b5c 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -83,29 +83,6 @@ ok1: MOVD $0, err+48(FP) // errno RET -// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 - MOVD a1+8(FP), R2 - MOVD a2+16(FP), R3 - MOVD a3+24(FP), R4 - MOVD a4+32(FP), R5 - MOVD a5+40(FP), R6 - MOVD a6+48(FP), R7 - MOVD trap+0(FP), R1 // syscall entry - SYSCALL - MOVD $0xfffffffffffff001, R8 - CMPUBLT R2, R8, ok2 - MOVD $-1, r1+56(FP) - MOVD $0, r2+64(FP) - NEG R2, R2 - MOVD R2, err+72(FP) // errno - RET -ok2: - MOVD R2, r1+56(FP) - MOVD R3, r2+64(FP) - MOVD $0, err+72(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD $0, R2 diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index a10bfbb0c9..b0e2cdb682 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -19,6 +19,12 @@ import ( func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) + +// N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. +// +// Errno is uintptr and thus compatible with the runtime/internal/syscall +// definition. + func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) -- cgit v1.2.3-54-g00ecf From f7b12ff6fbad25ea30ae9f16dd1443eb9b76766d Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 24 Feb 2022 16:46:54 -0500 Subject: syscall: define RawSyscall in terms of RawSyscall6 on linux For #51087 Change-Id: I63e07638507328efe33dbf7dd5f8a8b78890e037 Reviewed-on: https://go-review.googlesource.com/c/go/+/388476 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/syscall/asm_linux_386.s | 22 ---------------------- src/syscall/asm_linux_amd64.s | 20 -------------------- src/syscall/asm_linux_arm.s | 24 ------------------------ src/syscall/asm_linux_arm64.s | 23 ----------------------- src/syscall/asm_linux_mips64x.s | 21 --------------------- src/syscall/asm_linux_mipsx.s | 18 ------------------ src/syscall/asm_linux_ppc64x.s | 21 --------------------- src/syscall/asm_linux_riscv64.s | 21 --------------------- src/syscall/asm_linux_s390x.s | 23 ----------------------- src/syscall/syscall_linux.go | 22 +++++++++++++++++++++- 10 files changed, 21 insertions(+), 194 deletions(-) diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index a2b5efb2db..546d27932d 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -65,28 +65,6 @@ ok6: CALL runtime·exitsyscall(SB) RET -// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - MOVL trap+0(FP), AX // syscall entry - MOVL a1+4(FP), BX - MOVL a2+8(FP), CX - MOVL a3+12(FP), DX - MOVL $0, SI - MOVL $0, DI - INVOKE_SYSCALL - CMPL AX, $0xfffff001 - JLS ok1 - MOVL $-1, r1+16(FP) - MOVL $0, r2+20(FP) - NEGL AX - MOVL AX, err+24(FP) - RET -ok1: - MOVL AX, r1+16(FP) - MOVL DX, r2+20(FP) - MOVL $0, err+24(FP) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVL trap+0(FP), AX // syscall entry diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index a98125903a..bd50b5ebfe 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -64,26 +64,6 @@ ok6: CALL runtime·exitsyscall(SB) RET -// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOVQ a1+8(FP), DI - MOVQ a2+16(FP), SI - MOVQ a3+24(FP), DX - MOVQ trap+0(FP), AX // syscall entry - SYSCALL - CMPQ AX, $0xfffffffffffff001 - JLS ok1 - MOVQ $-1, r1+32(FP) - MOVQ $0, r2+40(FP) - NEGQ AX - MOVQ AX, err+48(FP) - RET -ok1: - MOVQ AX, r1+32(FP) - MOVQ DX, r2+40(FP) - MOVQ $0, err+48(FP) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVQ a1+8(FP), DI diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 50103172ba..12986f801e 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -102,30 +102,6 @@ okseek: BL runtime·exitsyscall(SB) RET -// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); -TEXT ·RawSyscall(SB),NOSPLIT,$0-28 - MOVW trap+0(FP), R7 // syscall entry - MOVW a1+4(FP), R0 - MOVW a2+8(FP), R1 - MOVW a3+12(FP), R2 - SWI $0 - MOVW $0xfffff001, R1 - CMP R1, R0 - BLS ok1 - MOVW $-1, R1 - MOVW R1, r1+16(FP) - MOVW $0, R2 - MOVW R2, r2+20(FP) - RSB $0, R0, R0 - MOVW R0, err+24(FP) - RET -ok1: - MOVW R0, r1+16(FP) - MOVW $0, R0 - MOVW R0, r2+20(FP) - MOVW R0, err+24(FP) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVW trap+0(FP), R7 // syscall entry diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index c9c6bfab09..fc1466cc80 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -57,29 +57,6 @@ ok: BL runtime·exitsyscall(SB) RET -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOVD a1+8(FP), R0 - MOVD a2+16(FP), R1 - MOVD a3+24(FP), R2 - MOVD $0, R3 - MOVD $0, R4 - MOVD $0, R5 - MOVD trap+0(FP), R8 // syscall entry - SVC - CMN $4095, R0 - BCC ok - MOVD $-1, R4 - MOVD R4, r1+32(FP) // r1 - MOVD ZR, r2+40(FP) // r2 - NEG R0, R0 - MOVD R0, err+48(FP) // errno - RET -ok: - MOVD R0, r1+32(FP) // r1 - MOVD R1, r2+40(FP) // r2 - MOVD ZR, err+48(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index bc2f72c965..b6f293471d 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -59,27 +59,6 @@ ok6: JAL runtime·exitsyscall(SB) RET -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOVV a1+8(FP), R4 - MOVV a2+16(FP), R5 - MOVV a3+24(FP), R6 - MOVV R0, R7 - MOVV R0, R8 - MOVV R0, R9 - MOVV trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok1 - MOVV $-1, R1 - MOVV R1, r1+32(FP) // r1 - MOVV R0, r2+40(FP) // r2 - MOVV R2, err+48(FP) // errno - RET -ok1: - MOVV R2, r1+32(FP) // r1 - MOVV R3, r2+40(FP) // r2 - MOVV R0, err+48(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 04fad404a4..041c353e79 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -97,24 +97,6 @@ ok9: JAL runtime·exitsyscall(SB) RET -TEXT ·RawSyscall(SB),NOSPLIT,$24-28 - MOVW a1+4(FP), R4 - MOVW a2+8(FP), R5 - MOVW a3+12(FP), R6 - MOVW trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok1 - MOVW $-1, R1 - MOVW R1, r1+16(FP) // r1 - MOVW R0, r2+20(FP) // r2 - MOVW R2, err+24(FP) // errno - RET -ok1: - MOVW R2, r1+16(FP) // r1 - MOVW R3, r2+20(FP) // r2 - MOVW R0, err+24(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVW a1+4(FP), R4 diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index 4c9c383ff0..b03d859ca2 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -59,27 +59,6 @@ ok6: BL runtime·exitsyscall(SB) RET -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOVD a1+8(FP), R3 - MOVD a2+16(FP), R4 - MOVD a3+24(FP), R5 - MOVD R0, R6 - MOVD R0, R7 - MOVD R0, R8 - MOVD trap+0(FP), R9 // syscall entry - SYSCALL R9 - BVC ok1 - MOVD $-1, R4 - MOVD R4, r1+32(FP) // r1 - MOVD R0, r2+40(FP) // r2 - MOVD R3, err+48(FP) // errno - RET -ok1: - MOVD R3, r1+32(FP) // r1 - MOVD R0, r2+40(FP) // r2 - MOVD R0, err+48(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index c7e1003997..f6b7d11c08 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -59,27 +59,6 @@ err: CALL runtime·exitsyscall(SB) RET -// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOV a1+8(FP), A0 - MOV a2+16(FP), A1 - MOV a3+24(FP), A2 - MOV trap+0(FP), A7 // syscall entry - ECALL - MOV $-4096, T0 - BLTU T0, A0, err - MOV A0, r1+32(FP) // r1 - MOV A1, r2+40(FP) // r2 - MOV ZERO, err+48(FP) // errno - RET -err: - MOV $-1, T0 - MOV T0, r1+32(FP) // r1 - MOV ZERO, r2+40(FP) // r2 - SUB A0, ZERO, A0 - MOV A0, err+48(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOV a1+8(FP), A0 diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 3fbda38b5c..0a4913779a 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -60,29 +60,6 @@ ok6: BL runtime·exitsyscall(SB) RET -// func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) -TEXT ·RawSyscall(SB),NOSPLIT,$0-56 - MOVD a1+8(FP), R2 - MOVD a2+16(FP), R3 - MOVD a3+24(FP), R4 - MOVD $0, R5 - MOVD $0, R6 - MOVD $0, R7 - MOVD trap+0(FP), R1 // syscall entry - SYSCALL - MOVD $0xfffffffffffff001, R8 - CMPUBLT R2, R8, ok1 - MOVD $-1, r1+32(FP) - MOVD $0, r2+40(FP) - NEG R2, R2 - MOVD R2, err+48(FP) // errno - RET -ok1: - MOVD R2, r1+32(FP) - MOVD R3, r2+40(FP) - MOVD $0, err+48(FP) // errno - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD $0, R2 diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index b0e2cdb682..a9a8ecbefd 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -18,7 +18,6 @@ import ( func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) // N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. // @@ -27,6 +26,27 @@ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +// N.B. For the Syscall functions below: +// +// //go:uintptrkeepalive because the uintptr argument may be converted pointers +// that need to be kept alive in the caller (this is implied for RawSyscall6 +// since it has no body). +// +// //go:nosplit because stack copying does not account for uintptrkeepalive, so +// the stack must not grow. Stack copying cannot blindly assume that all +// uintptr arguments are pointers, because some values may look like pointers, +// but not really be pointers, and adjusting their value would break the call. +// +// //go:linkname to ensure ABI wrappers are generated for external callers +// (notably x/sys/unix assembly). + +//go:uintptrkeepalive +//go:nosplit +//go:linkname RawSyscall +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + return RawSyscall6(trap, a1, a2, a3, 0, 0, 0) +} + func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* -- cgit v1.2.3-54-g00ecf From 64e69d3925e2d1f3fb903a2b4f422cf1cbc49ec1 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 24 Feb 2022 16:54:13 -0500 Subject: syscall: define Syscall in terms of RawSyscall on linux For #51087 Change-Id: I9de7e85ccf137ae73662759382334bcbe7208150 Reviewed-on: https://go-review.googlesource.com/c/go/+/388477 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/runtime/proc.go | 2 +- src/syscall/asm_linux_386.s | 26 -------------------------- src/syscall/asm_linux_amd64.s | 27 --------------------------- src/syscall/asm_linux_arm.s | 30 ------------------------------ src/syscall/asm_linux_arm64.s | 27 --------------------------- src/syscall/asm_linux_mips64x.s | 25 ------------------------- src/syscall/asm_linux_mipsx.s | 23 ----------------------- src/syscall/asm_linux_ppc64x.s | 25 ------------------------- src/syscall/asm_linux_riscv64.s | 24 ------------------------ src/syscall/asm_linux_s390x.s | 26 -------------------------- src/syscall/syscall_linux.go | 23 ++++++++++++++++++++++- 11 files changed, 23 insertions(+), 235 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 4535f62053..b281d9f3b8 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3658,7 +3658,7 @@ func reentersyscall(pc, sp uintptr) { // Standard syscall entry used by the go syscall library and normal cgo calls. // -// This is exported via linkname to assembly in the syscall package. +// This is exported via linkname to assembly in the syscall package and x/sys. // //go:nosplit //go:linkname entersyscall diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index 546d27932d..ae0047b6fb 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -13,32 +13,6 @@ // instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 -// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); -// Trap # in AX, args in BX CX DX SI DI, return in AX -TEXT ·Syscall(SB),NOSPLIT,$0-28 - CALL runtime·entersyscall(SB) - MOVL trap+0(FP), AX // syscall entry - MOVL a1+4(FP), BX - MOVL a2+8(FP), CX - MOVL a3+12(FP), DX - MOVL $0, SI - MOVL $0, DI - INVOKE_SYSCALL - CMPL AX, $0xfffff001 - JLS ok - MOVL $-1, r1+16(FP) - MOVL $0, r2+20(FP) - NEGL AX - MOVL AX, err+24(FP) - CALL runtime·exitsyscall(SB) - RET -ok: - MOVL AX, r1+16(FP) - MOVL DX, r2+20(FP) - MOVL $0, err+24(FP) - CALL runtime·exitsyscall(SB) - RET - // func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); TEXT ·Syscall6(SB),NOSPLIT,$0-40 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index bd50b5ebfe..ea939b39f0 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -11,33 +11,6 @@ #define SYS_gettimeofday 96 -// func Syscall(trap int64, a1, a2, a3 uintptr) (r1, r2, err uintptr); -// Trap # in AX, args in DI SI DX R10 R8 R9, return in AX DX -// Note that this differs from "standard" ABI convention, which -// would pass 4th arg in CX, not R10. - -TEXT ·Syscall(SB),NOSPLIT,$0-56 - CALL runtime·entersyscall(SB) - MOVQ a1+8(FP), DI - MOVQ a2+16(FP), SI - MOVQ a3+24(FP), DX - MOVQ trap+0(FP), AX // syscall entry - SYSCALL - CMPQ AX, $0xfffffffffffff001 - JLS ok - MOVQ $-1, r1+32(FP) - MOVQ $0, r2+40(FP) - NEGQ AX - MOVQ AX, err+48(FP) - CALL runtime·exitsyscall(SB) - RET -ok: - MOVQ AX, r1+32(FP) - MOVQ DX, r2+40(FP) - MOVQ $0, err+48(FP) - CALL runtime·exitsyscall(SB) - RET - // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 12986f801e..6f9a612fa1 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -9,36 +9,6 @@ // System calls for arm, Linux // -// func Syscall(syscall uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); -TEXT ·Syscall(SB),NOSPLIT,$0-28 - BL runtime·entersyscall(SB) - MOVW trap+0(FP), R7 - MOVW a1+4(FP), R0 - MOVW a2+8(FP), R1 - MOVW a3+12(FP), R2 - MOVW $0, R3 - MOVW $0, R4 - MOVW $0, R5 - SWI $0 - MOVW $0xfffff001, R1 - CMP R1, R0 - BLS ok - MOVW $-1, R1 - MOVW R1, r1+16(FP) - MOVW $0, R2 - MOVW R2, r2+20(FP) - RSB $0, R0, R0 - MOVW R0, err+24(FP) - BL runtime·exitsyscall(SB) - RET -ok: - MOVW R0, r1+16(FP) - MOVW $0, R0 - MOVW R0, r2+20(FP) - MOVW R0, err+24(FP) - BL runtime·exitsyscall(SB) - RET - // func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); // Actually Syscall5 but the rest of the code expects it to be named Syscall6. TEXT ·Syscall6(SB),NOSPLIT,$0-40 diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index fc1466cc80..c9d28d301a 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -4,33 +4,6 @@ #include "textflag.h" -// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); -TEXT ·Syscall(SB),NOSPLIT,$0-56 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R0 - MOVD a2+16(FP), R1 - MOVD a3+24(FP), R2 - MOVD $0, R3 - MOVD $0, R4 - MOVD $0, R5 - MOVD trap+0(FP), R8 // syscall entry - SVC - CMN $4095, R0 - BCC ok - MOVD $-1, R4 - MOVD R4, r1+32(FP) // r1 - MOVD ZR, r2+40(FP) // r2 - NEG R0, R0 - MOVD R0, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok: - MOVD R0, r1+32(FP) // r1 - MOVD R1, r2+40(FP) // r2 - MOVD ZR, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET - TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index b6f293471d..994d7779fb 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -10,31 +10,6 @@ // System calls for mips64, Linux // -// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); -TEXT ·Syscall(SB),NOSPLIT,$0-56 - JAL runtime·entersyscall(SB) - MOVV a1+8(FP), R4 - MOVV a2+16(FP), R5 - MOVV a3+24(FP), R6 - MOVV R0, R7 - MOVV R0, R8 - MOVV R0, R9 - MOVV trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok - MOVV $-1, R1 - MOVV R1, r1+32(FP) // r1 - MOVV R0, r2+40(FP) // r2 - MOVV R2, err+48(FP) // errno - JAL runtime·exitsyscall(SB) - RET -ok: - MOVV R2, r1+32(FP) // r1 - MOVV R3, r2+40(FP) // r2 - MOVV R0, err+48(FP) // errno - JAL runtime·exitsyscall(SB) - RET - TEXT ·Syscall6(SB),NOSPLIT,$0-80 JAL runtime·entersyscall(SB) MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 041c353e79..8c45861d64 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -11,29 +11,6 @@ // System calls for mips, Linux // -// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); -TEXT ·Syscall(SB),NOSPLIT,$0-28 - JAL runtime·entersyscall(SB) - MOVW a1+4(FP), R4 - MOVW a2+8(FP), R5 - MOVW a3+12(FP), R6 - MOVW R0, R7 - MOVW trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok - MOVW $-1, R1 - MOVW R1, r1+16(FP) // r1 - MOVW R0, r2+20(FP) // r2 - MOVW R2, err+24(FP) // errno - JAL runtime·exitsyscall(SB) - RET -ok: - MOVW R2, r1+16(FP) // r1 - MOVW R3, r2+20(FP) // r2 - MOVW R0, err+24(FP) // errno - JAL runtime·exitsyscall(SB) - RET - // func Syscall6(trap trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); // 5th and 6th arg go at sp+16, sp+20. // Note that frame size of 20 means that 24 bytes gets reserved on stack. diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index b03d859ca2..d60e472226 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -10,31 +10,6 @@ // System calls for ppc64, Linux // -// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); -TEXT ·Syscall(SB),NOSPLIT,$0-56 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R3 - MOVD a2+16(FP), R4 - MOVD a3+24(FP), R5 - MOVD R0, R6 - MOVD R0, R7 - MOVD R0, R8 - MOVD trap+0(FP), R9 // syscall entry - SYSCALL R9 - BVC ok - MOVD $-1, R4 - MOVD R4, r1+32(FP) // r1 - MOVD R0, r2+40(FP) // r2 - MOVD R3, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok: - MOVD R3, r1+32(FP) // r1 - MOVD R0, r2+40(FP) // r2 - MOVD R0, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET - TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index f6b7d11c08..60b5cdbc1c 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -8,30 +8,6 @@ // System calls for riscv64, Linux // -// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64) -TEXT ·Syscall(SB),NOSPLIT,$0-56 - CALL runtime·entersyscall(SB) - MOV a1+8(FP), A0 - MOV a2+16(FP), A1 - MOV a3+24(FP), A2 - MOV trap+0(FP), A7 // syscall entry - ECALL - MOV $-4096, T0 - BLTU T0, A0, err - MOV A0, r1+32(FP) // r1 - MOV A1, r2+40(FP) // r2 - MOV ZERO, err+48(FP) // errno - CALL runtime·exitsyscall(SB) - RET -err: - MOV $-1, T0 - MOV T0, r1+32(FP) // r1 - MOV ZERO, r2+40(FP) // r2 - SUB A0, ZERO, A0 - MOV A0, err+48(FP) // errno - CALL runtime·exitsyscall(SB) - RET - // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 0a4913779a..14dabd85c2 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -8,32 +8,6 @@ // System calls for s390x, Linux // -// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64) -TEXT ·Syscall(SB),NOSPLIT,$0-56 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R2 - MOVD a2+16(FP), R3 - MOVD a3+24(FP), R4 - MOVD $0, R5 - MOVD $0, R6 - MOVD $0, R7 - MOVD trap+0(FP), R1 // syscall entry - SYSCALL - MOVD $0xfffffffffffff001, R8 - CMPUBLT R2, R8, ok - MOVD $-1, r1+32(FP) - MOVD $0, r2+40(FP) - NEG R2, R2 - MOVD R2, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok: - MOVD R2, r1+32(FP) - MOVD R3, r2+40(FP) - MOVD $0, err+48(FP) // errno - BL runtime·exitsyscall(SB) - RET - // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index a9a8ecbefd..57e4769731 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -16,7 +16,6 @@ import ( "unsafe" ) -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) // N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. @@ -26,6 +25,18 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +// Pull in entersyscall/exitsyscall for Syscall/Syscall6. +// +// Note that this can't be a push linkname because the runtime already has a +// nameless linkname to export to assembly here and in x/sys. Additionally, +// entersyscall fetches the caller PC and SP and thus can't have a wrapper +// inbetween. + +//go:linkname runtime_entersyscall runtime.entersyscall +func runtime_entersyscall() +//go:linkname runtime_exitsyscall runtime.exitsyscall +func runtime_exitsyscall() + // N.B. For the Syscall functions below: // // //go:uintptrkeepalive because the uintptr argument may be converted pointers @@ -47,6 +58,16 @@ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { return RawSyscall6(trap, a1, a2, a3, 0, 0, 0) } +//go:uintptrkeepalive +//go:nosplit +//go:linkname Syscall +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + runtime_entersyscall() + r1, r2, err = RawSyscall(trap, a1, a2, a3) + runtime_exitsyscall() + return +} + func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* -- cgit v1.2.3-54-g00ecf From a56e2f672bda459b95cc9b2f287f895424643102 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 24 Feb 2022 17:00:12 -0500 Subject: syscall: define Syscall6 in terms of RawSyscall6 on linux For #51087 Change-Id: I4a5b5cb74f12db8999c6ff0e98c3034b58af3959 Reviewed-on: https://go-review.googlesource.com/c/go/+/388478 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/syscall/asm_linux_386.s | 26 -------------------------- src/syscall/asm_linux_amd64.s | 26 -------------------------- src/syscall/asm_linux_arm.s | 31 ------------------------------- src/syscall/asm_linux_arm64.s | 26 -------------------------- src/syscall/asm_linux_mips64x.s | 24 ------------------------ src/syscall/asm_linux_mipsx.s | 30 ------------------------------ src/syscall/asm_linux_ppc64x.s | 24 ------------------------ src/syscall/asm_linux_riscv64.s | 27 --------------------------- src/syscall/asm_linux_s390x.s | 26 -------------------------- src/syscall/syscall_linux.go | 12 ++++++++++-- 10 files changed, 10 insertions(+), 242 deletions(-) diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index ae0047b6fb..e86a859f4e 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -13,32 +13,6 @@ // instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 -// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - CALL runtime·entersyscall(SB) - MOVL trap+0(FP), AX // syscall entry - MOVL a1+4(FP), BX - MOVL a2+8(FP), CX - MOVL a3+12(FP), DX - MOVL a4+16(FP), SI - MOVL a5+20(FP), DI - MOVL a6+24(FP), BP - INVOKE_SYSCALL - CMPL AX, $0xfffff001 - JLS ok6 - MOVL $-1, r1+28(FP) - MOVL $0, r2+32(FP) - NEGL AX - MOVL AX, err+36(FP) - CALL runtime·exitsyscall(SB) - RET -ok6: - MOVL AX, r1+28(FP) - MOVL DX, r2+32(FP) - MOVL $0, err+36(FP) - CALL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVL trap+0(FP), AX // syscall entry diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index ea939b39f0..3206a45d5d 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -11,32 +11,6 @@ #define SYS_gettimeofday 96 -// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - CALL runtime·entersyscall(SB) - MOVQ a1+8(FP), DI - MOVQ a2+16(FP), SI - MOVQ a3+24(FP), DX - MOVQ a4+32(FP), R10 - MOVQ a5+40(FP), R8 - MOVQ a6+48(FP), R9 - MOVQ trap+0(FP), AX // syscall entry - SYSCALL - CMPQ AX, $0xfffffffffffff001 - JLS ok6 - MOVQ $-1, r1+56(FP) - MOVQ $0, r2+64(FP) - NEGQ AX - MOVQ AX, err+72(FP) - CALL runtime·exitsyscall(SB) - RET -ok6: - MOVQ AX, r1+56(FP) - MOVQ DX, r2+64(FP) - MOVQ $0, err+72(FP) - CALL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVQ a1+8(FP), DI diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 6f9a612fa1..3252220562 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -9,37 +9,6 @@ // System calls for arm, Linux // -// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); -// Actually Syscall5 but the rest of the code expects it to be named Syscall6. -TEXT ·Syscall6(SB),NOSPLIT,$0-40 - BL runtime·entersyscall(SB) - MOVW trap+0(FP), R7 // syscall entry - MOVW a1+4(FP), R0 - MOVW a2+8(FP), R1 - MOVW a3+12(FP), R2 - MOVW a4+16(FP), R3 - MOVW a5+20(FP), R4 - MOVW a6+24(FP), R5 - SWI $0 - MOVW $0xfffff001, R6 - CMP R6, R0 - BLS ok6 - MOVW $-1, R1 - MOVW R1, r1+28(FP) - MOVW $0, R2 - MOVW R2, r2+32(FP) - RSB $0, R0, R0 - MOVW R0, err+36(FP) - BL runtime·exitsyscall(SB) - RET -ok6: - MOVW R0, r1+28(FP) - MOVW R1, r2+32(FP) - MOVW $0, R0 - MOVW R0, err+36(FP) - BL runtime·exitsyscall(SB) - RET - #define SYS__LLSEEK 140 /* from zsysnum_linux_arm.go */ // func seek(fd int, offset int64, whence int) (newoffset int64, errno int) // Implemented in assembly to avoid allocation when diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index c9d28d301a..be78ac8ac4 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -4,32 +4,6 @@ #include "textflag.h" -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R0 - MOVD a2+16(FP), R1 - MOVD a3+24(FP), R2 - MOVD a4+32(FP), R3 - MOVD a5+40(FP), R4 - MOVD a6+48(FP), R5 - MOVD trap+0(FP), R8 // syscall entry - SVC - CMN $4095, R0 - BCC ok - MOVD $-1, R4 - MOVD R4, r1+56(FP) // r1 - MOVD ZR, r2+64(FP) // r2 - NEG R0, R0 - MOVD R0, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok: - MOVD R0, r1+56(FP) // r1 - MOVD R1, r2+64(FP) // r2 - MOVD ZR, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index 994d7779fb..fadf1939e0 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -10,30 +10,6 @@ // System calls for mips64, Linux // -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - JAL runtime·entersyscall(SB) - MOVV a1+8(FP), R4 - MOVV a2+16(FP), R5 - MOVV a3+24(FP), R6 - MOVV a4+32(FP), R7 - MOVV a5+40(FP), R8 - MOVV a6+48(FP), R9 - MOVV trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok6 - MOVV $-1, R1 - MOVV R1, r1+56(FP) // r1 - MOVV R0, r2+64(FP) // r2 - MOVV R2, err+72(FP) // errno - JAL runtime·exitsyscall(SB) - RET -ok6: - MOVV R2, r1+56(FP) // r1 - MOVV R3, r2+64(FP) // r2 - MOVV R0, err+72(FP) // errno - JAL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 8c45861d64..b8cae96b1a 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -11,36 +11,6 @@ // System calls for mips, Linux // -// func Syscall6(trap trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); -// 5th and 6th arg go at sp+16, sp+20. -// Note that frame size of 20 means that 24 bytes gets reserved on stack. -TEXT ·Syscall6(SB),NOSPLIT,$20-40 - NO_LOCAL_POINTERS - JAL runtime·entersyscall(SB) - MOVW a1+4(FP), R4 - MOVW a2+8(FP), R5 - MOVW a3+12(FP), R6 - MOVW a4+16(FP), R7 - MOVW a5+20(FP), R8 - MOVW a6+24(FP), R9 - MOVW R8, 16(R29) - MOVW R9, 20(R29) - MOVW trap+0(FP), R2 // syscall entry - SYSCALL - BEQ R7, ok6 - MOVW $-1, R1 - MOVW R1, r1+28(FP) // r1 - MOVW R0, r2+32(FP) // r2 - MOVW R2, err+36(FP) // errno - JAL runtime·exitsyscall(SB) - RET -ok6: - MOVW R2, r1+28(FP) // r1 - MOVW R3, r2+32(FP) // r2 - MOVW R0, err+36(FP) // errno - JAL runtime·exitsyscall(SB) - RET - // func Syscall9(trap trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr); // Actually Syscall8 but the rest of the code expects it to be named Syscall9. TEXT ·Syscall9(SB),NOSPLIT,$28-52 diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index d60e472226..89cc1c2b0b 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -10,30 +10,6 @@ // System calls for ppc64, Linux // -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R3 - MOVD a2+16(FP), R4 - MOVD a3+24(FP), R5 - MOVD a4+32(FP), R6 - MOVD a5+40(FP), R7 - MOVD a6+48(FP), R8 - MOVD trap+0(FP), R9 // syscall entry - SYSCALL R9 - BVC ok6 - MOVD $-1, R4 - MOVD R4, r1+56(FP) // r1 - MOVD R0, r2+64(FP) // r2 - MOVD R3, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok6: - MOVD R3, r1+56(FP) // r1 - MOVD R0, r2+64(FP) // r2 - MOVD R0, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index 60b5cdbc1c..0fc1f73581 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -8,33 +8,6 @@ // System calls for riscv64, Linux // -// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - CALL runtime·entersyscall(SB) - MOV a1+8(FP), A0 - MOV a2+16(FP), A1 - MOV a3+24(FP), A2 - MOV a4+32(FP), A3 - MOV a5+40(FP), A4 - MOV a6+48(FP), A5 - MOV trap+0(FP), A7 // syscall entry - ECALL - MOV $-4096, T0 - BLTU T0, A0, err - MOV A0, r1+56(FP) // r1 - MOV A1, r2+64(FP) // r2 - MOV ZERO, err+72(FP) // errno - CALL runtime·exitsyscall(SB) - RET -err: - MOV $-1, T0 - MOV T0, r1+56(FP) // r1 - MOV ZERO, r2+64(FP) // r2 - SUB A0, ZERO, A0 - MOV A0, err+72(FP) // errno - CALL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOV a1+8(FP), A0 diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 14dabd85c2..c3631c1261 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -8,32 +8,6 @@ // System calls for s390x, Linux // -// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R2 - MOVD a2+16(FP), R3 - MOVD a3+24(FP), R4 - MOVD a4+32(FP), R5 - MOVD a5+40(FP), R6 - MOVD a6+48(FP), R7 - MOVD trap+0(FP), R1 // syscall entry - SYSCALL - MOVD $0xfffffffffffff001, R8 - CMPUBLT R2, R8, ok6 - MOVD $-1, r1+56(FP) - MOVD $0, r2+64(FP) - NEG R2, R2 - MOVD R2, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET -ok6: - MOVD R2, r1+56(FP) - MOVD R3, r2+64(FP) - MOVD $0, err+72(FP) // errno - BL runtime·exitsyscall(SB) - RET - // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD $0, R2 diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 57e4769731..a796d17066 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -16,8 +16,6 @@ import ( "unsafe" ) -func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - // N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. // // Errno is uintptr and thus compatible with the runtime/internal/syscall @@ -68,6 +66,16 @@ func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { return } +//go:uintptrkeepalive +//go:nosplit +//go:linkname Syscall6 +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + runtime_entersyscall() + r1, r2, err = RawSyscall6(trap, a1, a2, a3, a4, a5, a6) + runtime_exitsyscall() + return +} + func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* -- cgit v1.2.3-54-g00ecf From 5b32a6f1793bbac820bc70066cb8f569edcaa982 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 19 Apr 2022 16:27:57 -0400 Subject: runtime/internal/syscall: use ABIInternal for Syscall6 on amd64 For #51087. Change-Id: I25971760b63ec0d23d0f011521dd197d81a38976 Reviewed-on: https://go-review.googlesource.com/c/go/+/401096 Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/runtime/internal/syscall/asm_linux_amd64.s | 44 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/runtime/internal/syscall/asm_linux_amd64.s b/src/runtime/internal/syscall/asm_linux_amd64.s index 961d9bd640..3740ef1beb 100644 --- a/src/runtime/internal/syscall/asm_linux_amd64.s +++ b/src/runtime/internal/syscall/asm_linux_amd64.s @@ -6,28 +6,42 @@ // func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) // -// Syscall # in AX, args in DI SI DX R10 R8 R9, return in AX DX. +// We need to convert to the syscall ABI. +// +// arg | ABIInternal | Syscall +// --------------------------- +// num | AX | AX +// a1 | BX | DI +// a2 | CX | SI +// a3 | DI | DX +// a4 | SI | R10 +// a5 | R8 | R8 +// a6 | R9 | R9 +// +// r1 | AX | AX +// r2 | BX | DX +// err | CX | part of AX // // Note that this differs from "standard" ABI convention, which would pass 4th // arg in CX, not R10. -TEXT ·Syscall6(SB),NOSPLIT,$0-80 - MOVQ num+0(FP), AX // syscall entry - MOVQ a1+8(FP), DI - MOVQ a2+16(FP), SI - MOVQ a3+24(FP), DX - MOVQ a4+32(FP), R10 - MOVQ a5+40(FP), R8 - MOVQ a6+48(FP), R9 +TEXT ·Syscall6(SB),NOSPLIT,$0 + // a6 already in R9. + // a5 already in R8. + MOVQ SI, R10 // a4 + MOVQ DI, DX // a3 + MOVQ CX, SI // a2 + MOVQ BX, DI // a1 + // num already in AX. SYSCALL CMPQ AX, $0xfffffffffffff001 JLS ok - MOVQ $-1, r1+56(FP) - MOVQ $0, r2+64(FP) NEGQ AX - MOVQ AX, errno+72(FP) + MOVQ AX, CX // errno + MOVQ $-1, AX // r1 + MOVQ $0, BX // r2 RET ok: - MOVQ AX, r1+56(FP) - MOVQ DX, r2+64(FP) - MOVQ $0, errno+72(FP) + // r1 already in AX. + MOVQ DX, BX // r2 + MOVQ $0, CX // errno RET -- cgit v1.2.3-54-g00ecf From f95db21332118134973ba046c4f5d0e890e36066 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 12 Apr 2022 15:17:18 -0400 Subject: cmd/go: add a better error message when in a module outside workspace When the user is trying to list or build a package in a module that's outside of the workspace provide a more clear message hinting to the user that they can add the module to the workspace using go work use. Fixes #51604 Change-Id: I1202ecb2f22fd6351bfdec88ed613b8167687fb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/400014 Run-TryBot: Michael Matloob Reviewed-by: Michael Matloob Auto-Submit: Michael Matloob Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/internal/modload/load.go | 8 +++++--- src/cmd/go/testdata/script/work_module_not_in_go_work.txt | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index e85a33dd50..7f1a88ffe7 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -605,11 +605,13 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str pkg := pathInModuleCache(ctx, absDir, rs) if pkg == "" { - scope := "main module or its selected dependencies" if inWorkspaceMode() { - scope = "modules listed in go.work or their selected dependencies" + if mr := findModuleRoot(absDir); mr != "" { + return "", fmt.Errorf("directory %s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using go work use %s", base.ShortPath(absDir), base.ShortPath(mr)) + } + return "", fmt.Errorf("directory %s outside modules listed in go.work or their selected dependencies", base.ShortPath(absDir)) } - return "", fmt.Errorf("directory %s outside %s", base.ShortPath(absDir), scope) + return "", fmt.Errorf("directory %s outside main module or its selected dependencies", base.ShortPath(absDir)) } return pkg, nil } diff --git a/src/cmd/go/testdata/script/work_module_not_in_go_work.txt b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt index 23d908c302..9109b2de7f 100644 --- a/src/cmd/go/testdata/script/work_module_not_in_go_work.txt +++ b/src/cmd/go/testdata/script/work_module_not_in_go_work.txt @@ -6,8 +6,8 @@ ! go list ./... stderr 'pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies' -! go list ./a -stderr 'directory a outside modules listed in go.work' +! go list ./a/c +stderr 'directory a[\\/]c is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using go work use a' -- go.work -- go 1.18 @@ -19,6 +19,8 @@ module example.com/a go 1.18 -- a/a.go -- package a +-- a/c/c.go -- +package c -- b/go.mod -- module example.com/b -- cgit v1.2.3-54-g00ecf From a4ded4b5ff90a58d1ecf55914af941c468a502f1 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 13 Apr 2022 14:35:15 -0700 Subject: misc/cgo/test: remove timing dependency from TestParallelSleep Rename it TestIssue1560 since it no longer sleeps. For #1560 Fixes #45586 Change-Id: I338eee9de43e871da142143943e9435218438e90 Reviewed-on: https://go-review.googlesource.com/c/go/+/400194 Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor TryBot-Result: Gopher Robot --- misc/cgo/test/callback_c.c | 31 ++++----------------------- misc/cgo/test/cgo_test.go | 2 +- misc/cgo/test/testx.go | 53 ++++++++++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 53 deletions(-) diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c index 8921b7306c..8ecf70f272 100644 --- a/misc/cgo/test/callback_c.c +++ b/misc/cgo/test/callback_c.c @@ -3,8 +3,7 @@ // license that can be found in the LICENSE file. #include -#include -#include + #include "_cgo_export.h" void @@ -31,32 +30,10 @@ IntoC(void) BackIntoGo(); } -#ifdef WIN32 -#include -long long -mysleep(int seconds) { - long long st = GetTickCount(); - Sleep(1000 * seconds); - return st; -} -#else -#include -long long -mysleep(int seconds) { - long long st; - struct timeval tv; - gettimeofday(&tv, NULL); - st = tv.tv_sec * 1000 + tv.tv_usec / 1000; - sleep(seconds); - return st; -} -#endif - -long long -twoSleep(int n) +void +Issue1560InC(void) { - BackgroundSleep(n); - return mysleep(n); + Issue1560FromC(); } void diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index 774277e10d..dee6164354 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -11,6 +11,7 @@ import "testing" // These wrappers are here for gotest to find. func Test1328(t *testing.T) { test1328(t) } +func Test1560(t *testing.T) { test1560(t) } func Test1635(t *testing.T) { test1635(t) } func Test3250(t *testing.T) { test3250(t) } func Test3729(t *testing.T) { test3729(t) } @@ -89,7 +90,6 @@ func TestLibgcc(t *testing.T) { testLibgcc(t) } func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } func TestNaming(t *testing.T) { testNaming(t) } func TestPanicFromC(t *testing.T) { testPanicFromC(t) } -func TestParallelSleep(t *testing.T) { testParallelSleep(t) } func TestPrintf(t *testing.T) { testPrintf(t) } func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) } func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) } diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go index 8ec84a8b22..6a8e97ddf3 100644 --- a/misc/cgo/test/testx.go +++ b/misc/cgo/test/testx.go @@ -18,7 +18,6 @@ import ( "sync" "sync/atomic" "testing" - "time" "unsafe" ) @@ -30,8 +29,7 @@ extern void doAdd(int, int); void IntoC(void); // issue 1560 -// mysleep returns the absolute start time in ms. -long long mysleep(int seconds); +extern void Issue1560InC(void); // twoSleep returns the absolute start time of the first sleep // in ms. @@ -183,35 +181,40 @@ func test1328(t *testing.T) { } // issue 1560 +// Test that C functions and Go functions run in parallel. -var sleepDone = make(chan int64) +var ( + issue1560 int32 -// parallelSleep returns the absolute difference between the start time -// of the two sleeps. -func parallelSleep(n int) int64 { - t := int64(C.twoSleep(C.int(n))) - <-sleepDone - if t < 0 { - return -t + issue1560Ch = make(chan bool, 2) +) + +//export Issue1560FromC +func Issue1560FromC() { + for atomic.LoadInt32(&issue1560) != 1 { + runtime.Gosched() + } + atomic.AddInt32(&issue1560, 1) + for atomic.LoadInt32(&issue1560) != 3 { + runtime.Gosched() } - return t + issue1560Ch <- true } -//export BackgroundSleep -func BackgroundSleep(n int32) { - go func() { - sleepDone <- int64(C.mysleep(C.int(n))) - }() +func Issue1560FromGo() { + atomic.AddInt32(&issue1560, 1) + for atomic.LoadInt32(&issue1560) != 2 { + runtime.Gosched() + } + atomic.AddInt32(&issue1560, 1) + issue1560Ch <- true } -func testParallelSleep(t *testing.T) { - sleepSec := 1 - dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond - t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt) - // bug used to run sleeps in serial, producing a 2*sleepSec-second delay. - // we detect if the start times of those sleeps are > 0.5*sleepSec-second. - if dt >= time.Duration(sleepSec)*time.Second/2 { - t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds()) - } +func test1560(t *testing.T) { + go Issue1560FromGo() + go C.Issue1560InC() + <-issue1560Ch + <-issue1560Ch } // issue 2462 -- cgit v1.2.3-54-g00ecf From 347534343b114d9183efeefcb1d49458e1e8e34f Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 21 Apr 2022 14:48:58 -0400 Subject: Revert "runtime/internal/syscall: use ABIInternal for Syscall6 on amd64" This reverts CL 401096. Grandparent CL 388477 breaks cmd/go TestScript/cover_pkgall_runtime. For #51087. For #52472. Change-Id: Ie82fe5f50975f66eb91fb0d01cd8bbbd0265eb4e Reviewed-on: https://go-review.googlesource.com/c/go/+/401634 Run-TryBot: Michael Pratt Auto-Submit: Michael Pratt Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/runtime/internal/syscall/asm_linux_amd64.s | 44 +++++++++----------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/src/runtime/internal/syscall/asm_linux_amd64.s b/src/runtime/internal/syscall/asm_linux_amd64.s index 3740ef1beb..961d9bd640 100644 --- a/src/runtime/internal/syscall/asm_linux_amd64.s +++ b/src/runtime/internal/syscall/asm_linux_amd64.s @@ -6,42 +6,28 @@ // func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) // -// We need to convert to the syscall ABI. -// -// arg | ABIInternal | Syscall -// --------------------------- -// num | AX | AX -// a1 | BX | DI -// a2 | CX | SI -// a3 | DI | DX -// a4 | SI | R10 -// a5 | R8 | R8 -// a6 | R9 | R9 -// -// r1 | AX | AX -// r2 | BX | DX -// err | CX | part of AX +// Syscall # in AX, args in DI SI DX R10 R8 R9, return in AX DX. // // Note that this differs from "standard" ABI convention, which would pass 4th // arg in CX, not R10. -TEXT ·Syscall6(SB),NOSPLIT,$0 - // a6 already in R9. - // a5 already in R8. - MOVQ SI, R10 // a4 - MOVQ DI, DX // a3 - MOVQ CX, SI // a2 - MOVQ BX, DI // a1 - // num already in AX. +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + MOVQ num+0(FP), AX // syscall entry + MOVQ a1+8(FP), DI + MOVQ a2+16(FP), SI + MOVQ a3+24(FP), DX + MOVQ a4+32(FP), R10 + MOVQ a5+40(FP), R8 + MOVQ a6+48(FP), R9 SYSCALL CMPQ AX, $0xfffffffffffff001 JLS ok + MOVQ $-1, r1+56(FP) + MOVQ $0, r2+64(FP) NEGQ AX - MOVQ AX, CX // errno - MOVQ $-1, AX // r1 - MOVQ $0, BX // r2 + MOVQ AX, errno+72(FP) RET ok: - // r1 already in AX. - MOVQ DX, BX // r2 - MOVQ $0, CX // errno + MOVQ AX, r1+56(FP) + MOVQ DX, r2+64(FP) + MOVQ $0, errno+72(FP) RET -- cgit v1.2.3-54-g00ecf From d35ec0b899fe1013af49adb92ef789e25797c2eb Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 21 Apr 2022 14:49:54 -0400 Subject: Revert "syscall: define Syscall6 in terms of RawSyscall6 on linux" This reverts CL 388478. Parent CL 388477 breaks cmd/go TestScript/cover_pkgall_runtime. For #51087. For #52472. Change-Id: Id5d5a4e138792cf130ecdcc6b996c8102d142a7e Reviewed-on: https://go-review.googlesource.com/c/go/+/401635 Run-TryBot: Michael Pratt Auto-Submit: Michael Pratt Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/syscall/asm_linux_386.s | 26 ++++++++++++++++++++++++++ src/syscall/asm_linux_amd64.s | 26 ++++++++++++++++++++++++++ src/syscall/asm_linux_arm.s | 31 +++++++++++++++++++++++++++++++ src/syscall/asm_linux_arm64.s | 26 ++++++++++++++++++++++++++ src/syscall/asm_linux_mips64x.s | 24 ++++++++++++++++++++++++ src/syscall/asm_linux_mipsx.s | 30 ++++++++++++++++++++++++++++++ src/syscall/asm_linux_ppc64x.s | 24 ++++++++++++++++++++++++ src/syscall/asm_linux_riscv64.s | 27 +++++++++++++++++++++++++++ src/syscall/asm_linux_s390x.s | 26 ++++++++++++++++++++++++++ src/syscall/syscall_linux.go | 12 ++---------- 10 files changed, 242 insertions(+), 10 deletions(-) diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index e86a859f4e..ae0047b6fb 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -13,6 +13,32 @@ // instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 +// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); +TEXT ·Syscall6(SB),NOSPLIT,$0-40 + CALL runtime·entersyscall(SB) + MOVL trap+0(FP), AX // syscall entry + MOVL a1+4(FP), BX + MOVL a2+8(FP), CX + MOVL a3+12(FP), DX + MOVL a4+16(FP), SI + MOVL a5+20(FP), DI + MOVL a6+24(FP), BP + INVOKE_SYSCALL + CMPL AX, $0xfffff001 + JLS ok6 + MOVL $-1, r1+28(FP) + MOVL $0, r2+32(FP) + NEGL AX + MOVL AX, err+36(FP) + CALL runtime·exitsyscall(SB) + RET +ok6: + MOVL AX, r1+28(FP) + MOVL DX, r2+32(FP) + MOVL $0, err+36(FP) + CALL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16 MOVL trap+0(FP), AX // syscall entry diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index 3206a45d5d..ea939b39f0 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -11,6 +11,32 @@ #define SYS_gettimeofday 96 +// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + CALL runtime·entersyscall(SB) + MOVQ a1+8(FP), DI + MOVQ a2+16(FP), SI + MOVQ a3+24(FP), DX + MOVQ a4+32(FP), R10 + MOVQ a5+40(FP), R8 + MOVQ a6+48(FP), R9 + MOVQ trap+0(FP), AX // syscall entry + SYSCALL + CMPQ AX, $0xfffffffffffff001 + JLS ok6 + MOVQ $-1, r1+56(FP) + MOVQ $0, r2+64(FP) + NEGQ AX + MOVQ AX, err+72(FP) + CALL runtime·exitsyscall(SB) + RET +ok6: + MOVQ AX, r1+56(FP) + MOVQ DX, r2+64(FP) + MOVQ $0, err+72(FP) + CALL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVQ a1+8(FP), DI diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 3252220562..6f9a612fa1 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -9,6 +9,37 @@ // System calls for arm, Linux // +// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); +// Actually Syscall5 but the rest of the code expects it to be named Syscall6. +TEXT ·Syscall6(SB),NOSPLIT,$0-40 + BL runtime·entersyscall(SB) + MOVW trap+0(FP), R7 // syscall entry + MOVW a1+4(FP), R0 + MOVW a2+8(FP), R1 + MOVW a3+12(FP), R2 + MOVW a4+16(FP), R3 + MOVW a5+20(FP), R4 + MOVW a6+24(FP), R5 + SWI $0 + MOVW $0xfffff001, R6 + CMP R6, R0 + BLS ok6 + MOVW $-1, R1 + MOVW R1, r1+28(FP) + MOVW $0, R2 + MOVW R2, r2+32(FP) + RSB $0, R0, R0 + MOVW R0, err+36(FP) + BL runtime·exitsyscall(SB) + RET +ok6: + MOVW R0, r1+28(FP) + MOVW R1, r2+32(FP) + MOVW $0, R0 + MOVW R0, err+36(FP) + BL runtime·exitsyscall(SB) + RET + #define SYS__LLSEEK 140 /* from zsysnum_linux_arm.go */ // func seek(fd int, offset int64, whence int) (newoffset int64, errno int) // Implemented in assembly to avoid allocation when diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index be78ac8ac4..c9d28d301a 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -4,6 +4,32 @@ #include "textflag.h" +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R0 + MOVD a2+16(FP), R1 + MOVD a3+24(FP), R2 + MOVD a4+32(FP), R3 + MOVD a5+40(FP), R4 + MOVD a6+48(FP), R5 + MOVD trap+0(FP), R8 // syscall entry + SVC + CMN $4095, R0 + BCC ok + MOVD $-1, R4 + MOVD R4, r1+56(FP) // r1 + MOVD ZR, r2+64(FP) // r2 + NEG R0, R0 + MOVD R0, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok: + MOVD R0, r1+56(FP) // r1 + MOVD R1, r2+64(FP) // r2 + MOVD ZR, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index fadf1939e0..994d7779fb 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -10,6 +10,30 @@ // System calls for mips64, Linux // +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + JAL runtime·entersyscall(SB) + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV a4+32(FP), R7 + MOVV a5+40(FP), R8 + MOVV a6+48(FP), R9 + MOVV trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok6 + MOVV $-1, R1 + MOVV R1, r1+56(FP) // r1 + MOVV R0, r2+64(FP) // r2 + MOVV R2, err+72(FP) // errno + JAL runtime·exitsyscall(SB) + RET +ok6: + MOVV R2, r1+56(FP) // r1 + MOVV R3, r2+64(FP) // r2 + MOVV R0, err+72(FP) // errno + JAL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index b8cae96b1a..8c45861d64 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -11,6 +11,36 @@ // System calls for mips, Linux // +// func Syscall6(trap trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); +// 5th and 6th arg go at sp+16, sp+20. +// Note that frame size of 20 means that 24 bytes gets reserved on stack. +TEXT ·Syscall6(SB),NOSPLIT,$20-40 + NO_LOCAL_POINTERS + JAL runtime·entersyscall(SB) + MOVW a1+4(FP), R4 + MOVW a2+8(FP), R5 + MOVW a3+12(FP), R6 + MOVW a4+16(FP), R7 + MOVW a5+20(FP), R8 + MOVW a6+24(FP), R9 + MOVW R8, 16(R29) + MOVW R9, 20(R29) + MOVW trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok6 + MOVW $-1, R1 + MOVW R1, r1+28(FP) // r1 + MOVW R0, r2+32(FP) // r2 + MOVW R2, err+36(FP) // errno + JAL runtime·exitsyscall(SB) + RET +ok6: + MOVW R2, r1+28(FP) // r1 + MOVW R3, r2+32(FP) // r2 + MOVW R0, err+36(FP) // errno + JAL runtime·exitsyscall(SB) + RET + // func Syscall9(trap trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr); // Actually Syscall8 but the rest of the code expects it to be named Syscall9. TEXT ·Syscall9(SB),NOSPLIT,$28-52 diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index 89cc1c2b0b..d60e472226 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -10,6 +10,30 @@ // System calls for ppc64, Linux // +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R3 + MOVD a2+16(FP), R4 + MOVD a3+24(FP), R5 + MOVD a4+32(FP), R6 + MOVD a5+40(FP), R7 + MOVD a6+48(FP), R8 + MOVD trap+0(FP), R9 // syscall entry + SYSCALL R9 + BVC ok6 + MOVD $-1, R4 + MOVD R4, r1+56(FP) // r1 + MOVD R0, r2+64(FP) // r2 + MOVD R3, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok6: + MOVD R3, r1+56(FP) // r1 + MOVD R0, r2+64(FP) // r2 + MOVD R0, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index 0fc1f73581..60b5cdbc1c 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -8,6 +8,33 @@ // System calls for riscv64, Linux // +// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + CALL runtime·entersyscall(SB) + MOV a1+8(FP), A0 + MOV a2+16(FP), A1 + MOV a3+24(FP), A2 + MOV a4+32(FP), A3 + MOV a5+40(FP), A4 + MOV a6+48(FP), A5 + MOV trap+0(FP), A7 // syscall entry + ECALL + MOV $-4096, T0 + BLTU T0, A0, err + MOV A0, r1+56(FP) // r1 + MOV A1, r2+64(FP) // r2 + MOV ZERO, err+72(FP) // errno + CALL runtime·exitsyscall(SB) + RET +err: + MOV $-1, T0 + MOV T0, r1+56(FP) // r1 + MOV ZERO, r2+64(FP) // r2 + SUB A0, ZERO, A0 + MOV A0, err+72(FP) // errno + CALL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOV a1+8(FP), A0 diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index c3631c1261..14dabd85c2 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -8,6 +8,32 @@ // System calls for s390x, Linux // +// func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R2 + MOVD a2+16(FP), R3 + MOVD a3+24(FP), R4 + MOVD a4+32(FP), R5 + MOVD a5+40(FP), R6 + MOVD a6+48(FP), R7 + MOVD trap+0(FP), R1 // syscall entry + SYSCALL + MOVD $0xfffffffffffff001, R8 + CMPUBLT R2, R8, ok6 + MOVD $-1, r1+56(FP) + MOVD $0, r2+64(FP) + NEG R2, R2 + MOVD R2, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok6: + MOVD R2, r1+56(FP) + MOVD R3, r2+64(FP) + MOVD $0, err+72(FP) // errno + BL runtime·exitsyscall(SB) + RET + // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32 MOVD $0, R2 diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index a796d17066..57e4769731 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -16,6 +16,8 @@ import ( "unsafe" ) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + // N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. // // Errno is uintptr and thus compatible with the runtime/internal/syscall @@ -66,16 +68,6 @@ func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { return } -//go:uintptrkeepalive -//go:nosplit -//go:linkname Syscall6 -func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { - runtime_entersyscall() - r1, r2, err = RawSyscall6(trap, a1, a2, a3, a4, a5, a6) - runtime_exitsyscall() - return -} - func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* -- cgit v1.2.3-54-g00ecf From aac1d3a1b12a290805ca35ff268738fb334b1ca4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 21 Apr 2022 14:50:45 -0400 Subject: Revert "syscall: define Syscall in terms of RawSyscall on linux" This reverts CL 388477, which breaks cmd/go TestScript/cover_pkgall_runtime. For #51087. For #52472. Change-Id: Id58af419a889281f15df2471c58fece011fcffbc Reviewed-on: https://go-review.googlesource.com/c/go/+/401636 Run-TryBot: Michael Pratt Auto-Submit: Michael Pratt Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/runtime/proc.go | 2 +- src/syscall/asm_linux_386.s | 26 ++++++++++++++++++++++++++ src/syscall/asm_linux_amd64.s | 27 +++++++++++++++++++++++++++ src/syscall/asm_linux_arm.s | 30 ++++++++++++++++++++++++++++++ src/syscall/asm_linux_arm64.s | 27 +++++++++++++++++++++++++++ src/syscall/asm_linux_mips64x.s | 25 +++++++++++++++++++++++++ src/syscall/asm_linux_mipsx.s | 23 +++++++++++++++++++++++ src/syscall/asm_linux_ppc64x.s | 25 +++++++++++++++++++++++++ src/syscall/asm_linux_riscv64.s | 24 ++++++++++++++++++++++++ src/syscall/asm_linux_s390x.s | 26 ++++++++++++++++++++++++++ src/syscall/syscall_linux.go | 23 +---------------------- 11 files changed, 235 insertions(+), 23 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index b281d9f3b8..4535f62053 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3658,7 +3658,7 @@ func reentersyscall(pc, sp uintptr) { // Standard syscall entry used by the go syscall library and normal cgo calls. // -// This is exported via linkname to assembly in the syscall package and x/sys. +// This is exported via linkname to assembly in the syscall package. // //go:nosplit //go:linkname entersyscall diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index ae0047b6fb..546d27932d 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -13,6 +13,32 @@ // instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 +// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); +// Trap # in AX, args in BX CX DX SI DI, return in AX +TEXT ·Syscall(SB),NOSPLIT,$0-28 + CALL runtime·entersyscall(SB) + MOVL trap+0(FP), AX // syscall entry + MOVL a1+4(FP), BX + MOVL a2+8(FP), CX + MOVL a3+12(FP), DX + MOVL $0, SI + MOVL $0, DI + INVOKE_SYSCALL + CMPL AX, $0xfffff001 + JLS ok + MOVL $-1, r1+16(FP) + MOVL $0, r2+20(FP) + NEGL AX + MOVL AX, err+24(FP) + CALL runtime·exitsyscall(SB) + RET +ok: + MOVL AX, r1+16(FP) + MOVL DX, r2+20(FP) + MOVL $0, err+24(FP) + CALL runtime·exitsyscall(SB) + RET + // func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); TEXT ·Syscall6(SB),NOSPLIT,$0-40 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index ea939b39f0..bd50b5ebfe 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -11,6 +11,33 @@ #define SYS_gettimeofday 96 +// func Syscall(trap int64, a1, a2, a3 uintptr) (r1, r2, err uintptr); +// Trap # in AX, args in DI SI DX R10 R8 R9, return in AX DX +// Note that this differs from "standard" ABI convention, which +// would pass 4th arg in CX, not R10. + +TEXT ·Syscall(SB),NOSPLIT,$0-56 + CALL runtime·entersyscall(SB) + MOVQ a1+8(FP), DI + MOVQ a2+16(FP), SI + MOVQ a3+24(FP), DX + MOVQ trap+0(FP), AX // syscall entry + SYSCALL + CMPQ AX, $0xfffffffffffff001 + JLS ok + MOVQ $-1, r1+32(FP) + MOVQ $0, r2+40(FP) + NEGQ AX + MOVQ AX, err+48(FP) + CALL runtime·exitsyscall(SB) + RET +ok: + MOVQ AX, r1+32(FP) + MOVQ DX, r2+40(FP) + MOVQ $0, err+48(FP) + CALL runtime·exitsyscall(SB) + RET + // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index 6f9a612fa1..12986f801e 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -9,6 +9,36 @@ // System calls for arm, Linux // +// func Syscall(syscall uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); +TEXT ·Syscall(SB),NOSPLIT,$0-28 + BL runtime·entersyscall(SB) + MOVW trap+0(FP), R7 + MOVW a1+4(FP), R0 + MOVW a2+8(FP), R1 + MOVW a3+12(FP), R2 + MOVW $0, R3 + MOVW $0, R4 + MOVW $0, R5 + SWI $0 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok + MOVW $-1, R1 + MOVW R1, r1+16(FP) + MOVW $0, R2 + MOVW R2, r2+20(FP) + RSB $0, R0, R0 + MOVW R0, err+24(FP) + BL runtime·exitsyscall(SB) + RET +ok: + MOVW R0, r1+16(FP) + MOVW $0, R0 + MOVW R0, r2+20(FP) + MOVW R0, err+24(FP) + BL runtime·exitsyscall(SB) + RET + // func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); // Actually Syscall5 but the rest of the code expects it to be named Syscall6. TEXT ·Syscall6(SB),NOSPLIT,$0-40 diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index c9d28d301a..fc1466cc80 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -4,6 +4,33 @@ #include "textflag.h" +// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); +TEXT ·Syscall(SB),NOSPLIT,$0-56 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R0 + MOVD a2+16(FP), R1 + MOVD a3+24(FP), R2 + MOVD $0, R3 + MOVD $0, R4 + MOVD $0, R5 + MOVD trap+0(FP), R8 // syscall entry + SVC + CMN $4095, R0 + BCC ok + MOVD $-1, R4 + MOVD R4, r1+32(FP) // r1 + MOVD ZR, r2+40(FP) // r2 + NEG R0, R0 + MOVD R0, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok: + MOVD R0, r1+32(FP) // r1 + MOVD R1, r2+40(FP) // r2 + MOVD ZR, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET + TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) MOVD a1+8(FP), R0 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index 994d7779fb..b6f293471d 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -10,6 +10,31 @@ // System calls for mips64, Linux // +// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); +TEXT ·Syscall(SB),NOSPLIT,$0-56 + JAL runtime·entersyscall(SB) + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV R0, R7 + MOVV R0, R8 + MOVV R0, R9 + MOVV trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVV $-1, R1 + MOVV R1, r1+32(FP) // r1 + MOVV R0, r2+40(FP) // r2 + MOVV R2, err+48(FP) // errno + JAL runtime·exitsyscall(SB) + RET +ok: + MOVV R2, r1+32(FP) // r1 + MOVV R3, r2+40(FP) // r2 + MOVV R0, err+48(FP) // errno + JAL runtime·exitsyscall(SB) + RET + TEXT ·Syscall6(SB),NOSPLIT,$0-80 JAL runtime·entersyscall(SB) MOVV a1+8(FP), R4 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 8c45861d64..041c353e79 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -11,6 +11,29 @@ // System calls for mips, Linux // +// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); +TEXT ·Syscall(SB),NOSPLIT,$0-28 + JAL runtime·entersyscall(SB) + MOVW a1+4(FP), R4 + MOVW a2+8(FP), R5 + MOVW a3+12(FP), R6 + MOVW R0, R7 + MOVW trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVW $-1, R1 + MOVW R1, r1+16(FP) // r1 + MOVW R0, r2+20(FP) // r2 + MOVW R2, err+24(FP) // errno + JAL runtime·exitsyscall(SB) + RET +ok: + MOVW R2, r1+16(FP) // r1 + MOVW R3, r2+20(FP) // r2 + MOVW R0, err+24(FP) // errno + JAL runtime·exitsyscall(SB) + RET + // func Syscall6(trap trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); // 5th and 6th arg go at sp+16, sp+20. // Note that frame size of 20 means that 24 bytes gets reserved on stack. diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index d60e472226..b03d859ca2 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -10,6 +10,31 @@ // System calls for ppc64, Linux // +// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64); +TEXT ·Syscall(SB),NOSPLIT,$0-56 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R3 + MOVD a2+16(FP), R4 + MOVD a3+24(FP), R5 + MOVD R0, R6 + MOVD R0, R7 + MOVD R0, R8 + MOVD trap+0(FP), R9 // syscall entry + SYSCALL R9 + BVC ok + MOVD $-1, R4 + MOVD R4, r1+32(FP) // r1 + MOVD R0, r2+40(FP) // r2 + MOVD R3, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok: + MOVD R3, r1+32(FP) // r1 + MOVD R0, r2+40(FP) // r2 + MOVD R0, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET + TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) MOVD a1+8(FP), R3 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index 60b5cdbc1c..f6b7d11c08 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -8,6 +8,30 @@ // System calls for riscv64, Linux // +// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64) +TEXT ·Syscall(SB),NOSPLIT,$0-56 + CALL runtime·entersyscall(SB) + MOV a1+8(FP), A0 + MOV a2+16(FP), A1 + MOV a3+24(FP), A2 + MOV trap+0(FP), A7 // syscall entry + ECALL + MOV $-4096, T0 + BLTU T0, A0, err + MOV A0, r1+32(FP) // r1 + MOV A1, r2+40(FP) // r2 + MOV ZERO, err+48(FP) // errno + CALL runtime·exitsyscall(SB) + RET +err: + MOV $-1, T0 + MOV T0, r1+32(FP) // r1 + MOV ZERO, r2+40(FP) // r2 + SUB A0, ZERO, A0 + MOV A0, err+48(FP) // errno + CALL runtime·exitsyscall(SB) + RET + // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 CALL runtime·entersyscall(SB) diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 14dabd85c2..0a4913779a 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -8,6 +8,32 @@ // System calls for s390x, Linux // +// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64) +TEXT ·Syscall(SB),NOSPLIT,$0-56 + BL runtime·entersyscall(SB) + MOVD a1+8(FP), R2 + MOVD a2+16(FP), R3 + MOVD a3+24(FP), R4 + MOVD $0, R5 + MOVD $0, R6 + MOVD $0, R7 + MOVD trap+0(FP), R1 // syscall entry + SYSCALL + MOVD $0xfffffffffffff001, R8 + CMPUBLT R2, R8, ok + MOVD $-1, r1+32(FP) + MOVD $0, r2+40(FP) + NEG R2, R2 + MOVD R2, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET +ok: + MOVD R2, r1+32(FP) + MOVD R3, r2+40(FP) + MOVD $0, err+48(FP) // errno + BL runtime·exitsyscall(SB) + RET + // func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) TEXT ·Syscall6(SB),NOSPLIT,$0-80 BL runtime·entersyscall(SB) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 57e4769731..a9a8ecbefd 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -16,6 +16,7 @@ import ( "unsafe" ) +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) // N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall. @@ -25,18 +26,6 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -// Pull in entersyscall/exitsyscall for Syscall/Syscall6. -// -// Note that this can't be a push linkname because the runtime already has a -// nameless linkname to export to assembly here and in x/sys. Additionally, -// entersyscall fetches the caller PC and SP and thus can't have a wrapper -// inbetween. - -//go:linkname runtime_entersyscall runtime.entersyscall -func runtime_entersyscall() -//go:linkname runtime_exitsyscall runtime.exitsyscall -func runtime_exitsyscall() - // N.B. For the Syscall functions below: // // //go:uintptrkeepalive because the uintptr argument may be converted pointers @@ -58,16 +47,6 @@ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { return RawSyscall6(trap, a1, a2, a3, 0, 0, 0) } -//go:uintptrkeepalive -//go:nosplit -//go:linkname Syscall -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { - runtime_entersyscall() - r1, r2, err = RawSyscall(trap, a1, a2, a3) - runtime_exitsyscall() - return -} - func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) /* -- cgit v1.2.3-54-g00ecf From 4d96c3cdadb7de81ced18eceaa906f35730523f4 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 21 Apr 2022 13:47:26 -0700 Subject: crypto/x509: revert serial length restriction This reverts CL400377, which restricted serials passed to x509.CreateCertificate to <= 20 octets. Unfortunately this turns out to be something _a lot_ of people get wrong. Since it's not particularly obvious how to properly generate conformant serials, until we provide an easier way for people to get this right, reverting this restriction makes sense (possible solution discussed in #52444.) Change-Id: Ia85a0ffe61e2e547abdaf1389c3e1ad29e28a2be Reviewed-on: https://go-review.googlesource.com/c/go/+/401657 Reviewed-by: Roland Shoemaker Run-TryBot: Roland Shoemaker Auto-Submit: Roland Shoemaker TryBot-Result: Gopher Robot Reviewed-by: Damien Neil --- src/crypto/x509/x509.go | 15 ++++----------- src/crypto/x509/x509_test.go | 36 ------------------------------------ 2 files changed, 4 insertions(+), 47 deletions(-) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index ceb04ae20e..582e1b1519 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -1478,21 +1478,14 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv return nil, errors.New("x509: no SerialNumber given") } - // RFC 5280 Section 4.1.2.2: serial number must positive and should not be longer - // than 20 octets. + // RFC 5280 Section 4.1.2.2: serial number must positive // - // We cannot simply check for len(serialBytes) > 20, because encoding/asn1 may - // pad the slice in order to prevent the integer being mistaken for a negative - // number (DER uses the high bit of the left-most byte to indicate the sign.), - // so we need to double check the composition of the serial if it is exactly - // 20 bytes. + // We _should_ also restrict serials to <= 20 octets, but it turns out a lot of people + // get this wrong, in part because the encoding can itself alter the length of the + // serial. For now we accept these non-conformant serials. if template.SerialNumber.Sign() == -1 { return nil, errors.New("x509: serial number must be positive") } - serialBytes := template.SerialNumber.Bytes() - if len(serialBytes) > 20 || (len(serialBytes) == 20 && serialBytes[0]&0x80 != 0) { - return nil, errors.New("x509: serial number exceeds 20 octets") - } if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) { return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 486d6bf3d2..f68dd0299a 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -3589,42 +3589,6 @@ func TestOmitEmptyExtensions(t *testing.T) { } } -func TestCreateCertificateLongSerial(t *testing.T) { - k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - t.Fatal(err) - } - - serialBytes := make([]byte, 21) - serialBytes[0] = 0x80 - serialBytes[20] = 1 - tooLong := big.NewInt(0).SetBytes(serialBytes) - - tmpl := &Certificate{ - SerialNumber: tooLong, - Subject: pkix.Name{ - CommonName: ":)", - }, - NotAfter: time.Now().Add(time.Hour), - NotBefore: time.Now().Add(-time.Hour), - } - - expectedErr := "x509: serial number exceeds 20 octets" - - _, err = CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k) - if err == nil || err.Error() != expectedErr { - t.Errorf("CreateCertificate returned unexpected error: want %q, got %q", expectedErr, err) - } - - serialBytes = serialBytes[:20] - tmpl.SerialNumber = big.NewInt(0).SetBytes(serialBytes) - - _, err = CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k) - if err == nil || err.Error() != expectedErr { - t.Errorf("CreateCertificate returned unexpected error: want %q, got %q", expectedErr, err) - } -} - var negativeSerialCert = `-----BEGIN CERTIFICATE----- MIIBBTCBraADAgECAgH/MAoGCCqGSM49BAMCMA0xCzAJBgNVBAMTAjopMB4XDTIy MDQxNDIzNTYwNFoXDTIyMDQxNTAxNTYwNFowDTELMAkGA1UEAxMCOikwWTATBgcq -- cgit v1.2.3-54-g00ecf From f5af1e83a526146a12af48df9d5c9851e24569d7 Mon Sep 17 00:00:00 2001 From: Daniel Martí Date: Thu, 21 Apr 2022 14:00:26 +0100 Subject: cmd/gofmt: only resolve go/ast objects when needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go/parser will by default resolve objects as per the go/ast.Object type, which is then used by gofmt's rewrite and simplify flags. However, none of that is needed if neither of the flags is set, so we can avoid the work entirely for a nice speed-up. benchcmd -n 8 GofmtSrcCmd gofmt -l ~/tip/src/cmd name old time/op new time/op delta GofmtSrcCmd 957ms ± 7% 908ms ± 7% -5.12% (p=0.028 n=8+8) name old user-time/op new user-time/op delta GofmtSrcCmd 11.2s ± 1% 10.4s ± 1% -7.23% (p=0.001 n=7+7) name old sys-time/op new sys-time/op delta GofmtSrcCmd 325ms ±29% 286ms ±22% ~ (p=0.065 n=8+8) name old peak-RSS-bytes new peak-RSS-bytes delta GofmtSrcCmd 295MB ±17% 276MB ±15% ~ (p=0.328 n=8+8) See #46485. Change-Id: Iad1ae294953710c233f7837d7eb02e23d11c6185 Reviewed-on: https://go-review.googlesource.com/c/go/+/401454 Run-TryBot: Daniel Martí TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor --- src/cmd/gofmt/gofmt.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 5fa883fb56..9b639bd996 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -76,6 +76,11 @@ func initParserMode() { if *allErrors { parserMode |= parser.AllErrors } + // Both -r and -s make use of go/ast's object resolution. + // If neither is being used, avoid that unnecessary work. + if *rewriteRule == "" && !*simplifyAST { + parserMode |= parser.SkipObjectResolution + } } func isGoFile(f fs.DirEntry) bool { -- cgit v1.2.3-54-g00ecf From 430ae97a2599e840bdeb934d5be171efb4a41272 Mon Sep 17 00:00:00 2001 From: Daniel Martí Date: Thu, 21 Apr 2022 14:06:20 +0100 Subject: go/format: skip go/ast's object resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like https://golang.org/cl/401454 removed the work from gofmt for a nice ~5% speed-up in the default case, we can also use the option in the equivalent go/format for programs which use it rather than gofmt, as go/format makes no use of objects either. No benchmark numbers as we already measured the ~5% speed-up with gofmt in the other CL linked above. See #46485. Change-Id: Icbf98e6d46a616081314e2faa13f1dfade3bbaef Reviewed-on: https://go-review.googlesource.com/c/go/+/401474 Run-TryBot: Daniel Martí TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor --- src/go/format/format.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/format/format.go b/src/go/format/format.go index fb87e84a4e..3837cb4617 100644 --- a/src/go/format/format.go +++ b/src/go/format/format.go @@ -38,7 +38,7 @@ const ( var config = printer.Config{Mode: printerMode, Tabwidth: tabWidth} -const parserMode = parser.ParseComments +const parserMode = parser.ParseComments | parser.SkipObjectResolution // Node formats node in canonical gofmt style and writes the result to dst. // -- cgit v1.2.3-54-g00ecf From 889a902d215c57fe2032181370a9a2c30c531c99 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 12 Jan 2022 18:27:28 -0500 Subject: cmd/trace: embed static content cmd/trace is currently somewhat painful to use in odd environments since it depends on the presence of $GOROOT/misc/trace to serve the static trace viewer content. Use //go:embed to embed this content directly into cmd/trace for easier use. Change-Id: I83b7d97dbecc9773f3b5a6b3bc4a6597473bc01a Reviewed-on: https://go-review.googlesource.com/c/go/+/378194 Run-TryBot: Michael Pratt Auto-Submit: Michael Pratt Reviewed-by: Michael Knyszek TryBot-Result: Gopher Robot --- misc/trace/README.md | 105 - misc/trace/trace_viewer_full.html | 10441 -------------------------- misc/trace/webcomponents.min.js | 14 - src/bootstrap.bash | 2 +- src/cmd/trace/static/README.md | 105 + src/cmd/trace/static/trace_viewer_full.html | 10441 ++++++++++++++++++++++++++ src/cmd/trace/static/webcomponents.min.js | 14 + src/cmd/trace/trace.go | 26 +- 8 files changed, 10570 insertions(+), 10578 deletions(-) delete mode 100644 misc/trace/README.md delete mode 100644 misc/trace/trace_viewer_full.html delete mode 100644 misc/trace/webcomponents.min.js create mode 100644 src/cmd/trace/static/README.md create mode 100644 src/cmd/trace/static/trace_viewer_full.html create mode 100644 src/cmd/trace/static/webcomponents.min.js diff --git a/misc/trace/README.md b/misc/trace/README.md deleted file mode 100644 index 218d728546..0000000000 --- a/misc/trace/README.md +++ /dev/null @@ -1,105 +0,0 @@ -## Resources for Go's trace viewer - -Go execution trace UI (`go tool trace`) embeds -Chrome's trace viewer (Catapult) following the -[instructions]( -https://chromium.googlesource.com/catapult/+/refs/heads/master/tracing/docs/embedding-trace-viewer.md). This directory contains -the helper files to embed Chrome's trace viewer. - -The current resources were generated/copied from -[`Catapult@9508452e18f130c98499cb4c4f1e1efaedee8962`]( -https://chromium.googlesource.com/catapult/+/9508452e18f130c98499cb4c4f1e1efaedee8962). - -### Updating `trace_viewer_full.html` - -The file was generated by catapult's `vulcanize_trace_viewer` command. -``` -$ git clone https://chromium.googlesource.com/catapult -$ cd catapult -$ ./tracing/bin/vulcanize_trace_viewer --config=full -$ cp tracing/bin/trace_viewer_full.html $GOROOT/misc/trace/trace_viewer_full.html -``` - -We are supposed to use --config=lean (produces smaller html), -but it is broken at the moment: -https://github.com/catapult-project/catapult/issues/2247 - -### Updating `webcomponents.min.js` - -`webcomponents.min.js` is necessary to let the trace viewer page -to import the `trace_viewer_full.html`. -This is copied from the catapult repo. - -``` -$ cp third_party/polymer/components/webcomponentsjs/webcomponents.min.js $GOROOT/misc/trace/webcomponents.min.js -``` - -## Licenses - -The license for trace-viewer is as follows: -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The license for webcomponents.min.js is as follows: - -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -// Copyright (c) 2014 The Polymer Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/misc/trace/trace_viewer_full.html b/misc/trace/trace_viewer_full.html deleted file mode 100644 index ae6e35fca2..0000000000 --- a/misc/trace/trace_viewer_full.html +++ /dev/null @@ -1,10441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/misc/trace/webcomponents.min.js b/misc/trace/webcomponents.min.js deleted file mode 100644 index ad8196bc30..0000000000 --- a/misc/trace/webcomponents.min.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -// @version 0.7.24 -!function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomponents.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOpts){if(location.search.slice(1).split("&").forEach(function(e){var t,r=e.split("=");r[0]&&(t=r[0].match(/wc-(.+)/))&&(n[t[1]]=r[1]||!0)}),t)for(var r,o=0;r=t.attributes[o];o++)"src"!==r.name&&(n[r.name]=r.value||!0);if(n.log&&n.log.split){var i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={}}n.shadow=n.shadow||n.shadowdom||n.polyfill,"native"===n.shadow?n.shadow=!1:n.shadow=n.shadow||!HTMLElement.prototype.createShadowRoot,n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=n.register),WebComponents.flags=n}(),WebComponents.flags.shadow&&("undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:function(t,n){var r=t[this.name];return r&&r[0]===t?r[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=n}(),window.ShadowDOMPolyfill={},function(e){"use strict";function t(){if("undefined"!=typeof chrome&&chrome.app&&chrome.app.runtime)return!1;if(navigator.getDeviceStorage)return!1;try{var e=new Function("return true;");return e()}catch(t){return!1}}function n(e){if(!e)throw new Error("Assertion failed")}function r(e,t){for(var n=W(t),r=0;r0||n>0;)if(0!=t)if(0!=n){var l,u=e[t-1][n-1],d=e[t-1][n],p=e[t][n-1];l=d0){for(var u=0;u0&&r.length>0;){var i=n.pop(),a=r.pop();if(i!==a)break;o=i}return o}function u(e,t,n){t instanceof G.Window&&(t=t.document);var o,i=A(t),a=A(n),s=r(n,e),o=l(i,a);o||(o=a.root);for(var c=o;c;c=c.parent)for(var u=0;u0;i--)if(!g(t[i],e,o,t,r))return!1;return!0}function w(e,t,n,r){var o=ie,i=t[0]||n;return g(i,e,o,t,r)}function v(e,t,n,r){for(var o=ae,i=1;i0&&g(n,e,o,t,r)}function g(e,t,n,r,o){var i=z.get(e);if(!i)return!0;var a=o||s(r,e);if(a===e){if(n===oe)return!0;n===ae&&(n=ie)}else if(n===ae&&!t.bubbles)return!0;if("relatedTarget"in t){var c=B(t),l=c.relatedTarget;if(l){if(l instanceof Object&&l.addEventListener){var d=V(l),p=u(t,e,d);if(p===a)return!0}else p=null;Z.set(t,p)}}J.set(t,n);var h=t.type,f=!1;X.set(t,a),Y.set(t,e),i.depth++;for(var m=0,w=i.length;m=0;a--)e.removeChild(i[a]),i[a].parentNode_=t;U=!1;for(var a=0;a>>/g," ")}function r(e){return String(e).replace(/:host\(([^\s]+)\)/g,"$1").replace(/([^\s]):host/g,"$1").replace(":host","*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content|>>>/g," ")}function o(e,t){for(var n,r=e.firstElementChild;r;){if(r.matches(t))return r;if(n=o(r,t))return n;r=r.nextElementSibling}return null}function i(e,t){return e.matches(t)}function a(e,t,n){var r=e.localName;return r===t||r===n&&e.namespaceURI===j}function s(){return!0}function c(e,t,n){return e.localName===n}function l(e,t){return e.namespaceURI===t}function u(e,t,n){return e.namespaceURI===t&&e.localName===n}function d(e,t,n,r,o,i){for(var a=e.firstElementChild;a;)r(a,o,i)&&(n[t++]=a),t=d(a,t,n,r,o,i),a=a.nextElementSibling;return t}function p(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,null);if(c instanceof N)s=S.call(c,i);else{if(!(c instanceof C))return d(this,r,o,n,i,null);s=_.call(c,i)}return t(s,r,o,a)}function h(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=M.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=T.call(c,i,a)}return t(s,r,o,!1)}function f(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=L.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=O.call(c,i,a)}return t(s,r,o,!1)}var m=e.wrappers.HTMLCollection,w=e.wrappers.NodeList,v=e.getTreeScope,g=e.unsafeUnwrap,b=e.wrap,y=document.querySelector,E=document.documentElement.querySelector,_=document.querySelectorAll,S=document.documentElement.querySelectorAll,T=document.getElementsByTagName,M=document.documentElement.getElementsByTagName,O=document.getElementsByTagNameNS,L=document.documentElement.getElementsByTagNameNS,N=window.Element,C=window.HTMLDocument||window.Document,j="http://www.w3.org/1999/xhtml",D={ -querySelector:function(t){var r=n(t),i=r!==t;t=r;var a,s=g(this),c=v(this).root;if(c instanceof e.wrappers.ShadowRoot)return o(this,t);if(s instanceof N)a=b(E.call(s,t));else{if(!(s instanceof C))return o(this,t);a=b(y.call(s,t))}return a&&!i&&(c=v(a).root)&&c instanceof e.wrappers.ShadowRoot?o(this,t):a},querySelectorAll:function(e){var t=n(e),r=t!==e;e=t;var o=new w;return o.length=p.call(this,i,0,o,e,r),o}},H={matches:function(t){return t=r(t),e.originalMatches.call(g(this),t)}},x={getElementsByTagName:function(e){var t=new m,n="*"===e?s:a;return t.length=h.call(this,n,0,t,e,e.toLowerCase()),t},getElementsByClassName:function(e){return this.querySelectorAll("."+e)},getElementsByTagNameNS:function(e,t){var n=new m,r=null;return r="*"===e?"*"===t?s:c:"*"===t?l:u,n.length=f.call(this,r,0,n,e||null,t),n}};e.GetElementsByInterface=x,e.SelectorsInterface=D,e.MatchesInterface=H}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;return e}function n(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.previousSibling;return e}var r=e.wrappers.NodeList,o={get firstElementChild(){return t(this.firstChild)},get lastElementChild(){return n(this.lastChild)},get childElementCount(){for(var e=0,t=this.firstElementChild;t;t=t.nextElementSibling)e++;return e},get children(){for(var e=new r,t=0,n=this.firstElementChild;n;n=n.nextElementSibling)e[t++]=n;return e.length=t,e},remove:function(){var e=this.parentNode;e&&e.removeChild(this)}},i={get nextElementSibling(){return t(this.nextSibling)},get previousElementSibling(){return n(this.previousSibling)}},a={getElementById:function(e){return/[ \t\n\r\f]/.test(e)?null:this.querySelector('[id="'+e+'"]')}};e.ChildNodeInterface=i,e.NonElementParentNodeInterface=a,e.ParentNodeInterface=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}var n=e.ChildNodeInterface,r=e.wrappers.Node,o=e.enqueueMutation,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=window.CharacterData;t.prototype=Object.create(r.prototype),i(t.prototype,{get nodeValue(){return this.data},set nodeValue(e){this.data=e},get textContent(){return this.data},set textContent(e){this.data=e},get data(){return s(this).data},set data(e){var t=s(this).data;o(this,"characterData",{oldValue:t}),s(this).data=e}}),i(t.prototype,n),a(c,t,document.createTextNode("")),e.wrappers.CharacterData=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e>>>0}function n(e){r.call(this,e)}var r=e.wrappers.CharacterData,o=(e.enqueueMutation,e.mixin),i=e.registerWrapper,a=window.Text;n.prototype=Object.create(r.prototype),o(n.prototype,{splitText:function(e){e=t(e);var n=this.data;if(e>n.length)throw new Error("IndexSizeError");var r=n.slice(0,e),o=n.slice(e);this.data=r;var i=this.ownerDocument.createTextNode(o);return this.parentNode&&this.parentNode.insertBefore(i,this.nextSibling),i}}),i(a,n,document.createTextNode("")),e.wrappers.Text=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return i(e).getAttribute("class")}function n(e,t){a(e,"attributes",{name:"class",namespace:null,oldValue:t})}function r(t){e.invalidateRendererBasedOnAttribute(t,"class")}function o(e,o,i){var a=e.ownerElement_;if(null==a)return o.apply(e,i);var s=t(a),c=o.apply(e,i);return t(a)!==s&&(n(a,s),r(a)),c}if(!window.DOMTokenList)return void console.warn("Missing DOMTokenList prototype, please include a compatible classList polyfill such as http://goo.gl/uTcepH.");var i=e.unsafeUnwrap,a=e.enqueueMutation,s=DOMTokenList.prototype.add;DOMTokenList.prototype.add=function(){o(this,s,arguments)};var c=DOMTokenList.prototype.remove;DOMTokenList.prototype.remove=function(){o(this,c,arguments)};var l=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(){return o(this,l,arguments)}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n){var r=t.parentNode;if(r&&r.shadowRoot){var o=e.getRendererForHost(r);o.dependsOnAttribute(n)&&o.invalidate()}}function n(e,t,n){u(e,"attributes",{name:t,namespace:null,oldValue:n})}function r(e){a.call(this,e)}var o=e.ChildNodeInterface,i=e.GetElementsByInterface,a=e.wrappers.Node,s=e.ParentNodeInterface,c=e.SelectorsInterface,l=e.MatchesInterface,u=(e.addWrapNodeListMethod,e.enqueueMutation),d=e.mixin,p=(e.oneOf,e.registerWrapper),h=e.unsafeUnwrap,f=e.wrappers,m=window.Element,w=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(e){return m.prototype[e]}),v=w[0],g=m.prototype[v],b=new WeakMap;r.prototype=Object.create(a.prototype),d(r.prototype,{createShadowRoot:function(){var t=new f.ShadowRoot(this);h(this).polymerShadowRoot_=t;var n=e.getRendererForHost(this);return n.invalidate(),t},get shadowRoot(){return h(this).polymerShadowRoot_||null},setAttribute:function(e,r){var o=h(this).getAttribute(e);h(this).setAttribute(e,r),n(this,e,o),t(this,e)},removeAttribute:function(e){var r=h(this).getAttribute(e);h(this).removeAttribute(e),n(this,e,r),t(this,e)},get classList(){var e=b.get(this);if(!e){if(e=h(this).classList,!e)return;e.ownerElement_=this,b.set(this,e)}return e},get className(){return h(this).className},set className(e){this.setAttribute("class",e)},get id(){return h(this).id},set id(e){this.setAttribute("id",e)}}),w.forEach(function(e){"matches"!==e&&(r.prototype[e]=function(e){return this.matches(e)})}),m.prototype.webkitCreateShadowRoot&&(r.prototype.webkitCreateShadowRoot=r.prototype.createShadowRoot),d(r.prototype,o),d(r.prototype,i),d(r.prototype,s),d(r.prototype,c),d(r.prototype,l),p(m,r,document.createElementNS(null,"x")),e.invalidateRendererBasedOnAttribute=t,e.matchesNames=w,e.originalMatches=g,e.wrappers.Element=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";case" ":return" "}}function n(e){return e.replace(L,t)}function r(e){return e.replace(N,t)}function o(e){for(var t={},n=0;n"):c+">"+s(e)+"";case Node.TEXT_NODE:var d=e.data;return t&&j[t.localName]?d:r(d);case Node.COMMENT_NODE:return"";default:throw console.error(e),new Error("not implemented")}}function s(e){e instanceof O.HTMLTemplateElement&&(e=e.content);for(var t="",n=e.firstChild;n;n=n.nextSibling)t+=a(n,e);return t}function c(e,t,n){var r=n||"div";e.textContent="";var o=T(e.ownerDocument.createElement(r));o.innerHTML=t;for(var i;i=o.firstChild;)e.appendChild(M(i))}function l(e){m.call(this,e)}function u(e,t){var n=T(e.cloneNode(!1));n.innerHTML=t;for(var r,o=T(document.createDocumentFragment());r=n.firstChild;)o.appendChild(r);return M(o)}function d(t){return function(){return e.renderAllPending(),S(this)[t]}}function p(e){w(l,e,d(e))}function h(t){Object.defineProperty(l.prototype,t,{get:d(t),set:function(n){e.renderAllPending(),S(this)[t]=n},configurable:!0,enumerable:!0})}function f(t){Object.defineProperty(l.prototype,t,{value:function(){return e.renderAllPending(),S(this)[t].apply(S(this),arguments)},configurable:!0,enumerable:!0})}var m=e.wrappers.Element,w=e.defineGetter,v=e.enqueueMutation,g=e.mixin,b=e.nodesWereAdded,y=e.nodesWereRemoved,E=e.registerWrapper,_=e.snapshotNodeList,S=e.unsafeUnwrap,T=e.unwrap,M=e.wrap,O=e.wrappers,L=/[&\u00A0"]/g,N=/[&\u00A0<>]/g,C=o(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),j=o(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D="http://www.w3.org/1999/xhtml",H=/MSIE/.test(navigator.userAgent),x=window.HTMLElement,R=window.HTMLTemplateElement;l.prototype=Object.create(m.prototype),g(l.prototype,{get innerHTML(){return s(this)},set innerHTML(e){if(H&&j[this.localName])return void(this.textContent=e);var t=_(this.childNodes);this.invalidateShadowRenderer()?this instanceof O.HTMLTemplateElement?c(this.content,e):c(this,e,this.tagName):!R&&this instanceof O.HTMLTemplateElement?c(this.content,e):S(this).innerHTML=e;var n=_(this.childNodes);v(this,"childList",{addedNodes:n,removedNodes:t}),y(t),b(n,this)},get outerHTML(){return a(this,this.parentNode)},set outerHTML(e){var t=this.parentNode;if(t){t.invalidateShadowRenderer();var n=u(t,e);t.replaceChild(n,this)}},insertAdjacentHTML:function(e,t){var n,r;switch(String(e).toLowerCase()){case"beforebegin":n=this.parentNode,r=this;break;case"afterend":n=this.parentNode,r=this.nextSibling;break;case"afterbegin":n=this,r=this.firstChild;break;case"beforeend":n=this,r=null;break;default:return}var o=u(n,t);n.insertBefore(o,r)},get hidden(){return this.hasAttribute("hidden")},set hidden(e){e?this.setAttribute("hidden",""):this.removeAttribute("hidden")}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(p),["scrollLeft","scrollTop"].forEach(h),["focus","getBoundingClientRect","getClientRects","scrollIntoView"].forEach(f),E(x,l,document.createElement("b")),e.wrappers.HTMLElement=l,e.getInnerHTML=s,e.setInnerHTML=c}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.HTMLCanvasElement;t.prototype=Object.create(n.prototype),r(t.prototype,{getContext:function(){var e=i(this).getContext.apply(i(this),arguments);return e&&a(e)}}),o(s,t,document.createElement("canvas")),e.wrappers.HTMLCanvasElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=window.HTMLContentElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get select(){return this.getAttribute("select")},set select(e){this.setAttribute("select",e)},setAttribute:function(e,t){n.prototype.setAttribute.call(this,e,t),"select"===String(e).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),i&&o(i,t),e.wrappers.HTMLContentElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=window.HTMLFormElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get elements(){return i(a(this).elements)}}),o(s,t,document.createElement("form")),e.wrappers.HTMLFormElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e,t){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var o=i(document.createElement("img"));r.call(this,o),a(o,this),void 0!==e&&(o.width=e),void 0!==t&&(o.height=t)}var r=e.wrappers.HTMLElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLImageElement;t.prototype=Object.create(r.prototype),o(s,t,document.createElement("img")),n.prototype=t.prototype,e.wrappers.HTMLImageElement=t,e.wrappers.Image=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=(e.mixin,e.wrappers.NodeList,e.registerWrapper),o=window.HTMLShadowElement;t.prototype=Object.create(n.prototype),t.prototype.constructor=t,o&&r(o,t),e.wrappers.HTMLShadowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){if(!e.defaultView)return e;var t=d.get(e);if(!t){for(t=e.implementation.createHTMLDocument("");t.lastChild;)t.removeChild(t.lastChild);d.set(e,t)}return t}function n(e){for(var n,r=t(e.ownerDocument),o=c(r.createDocumentFragment());n=e.firstChild;)o.appendChild(n);return o}function r(e){if(o.call(this,e),!p){var t=n(e);u.set(this,l(t))}}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.wrap,u=new WeakMap,d=new WeakMap,p=window.HTMLTemplateElement;r.prototype=Object.create(o.prototype),i(r.prototype,{constructor:r,get content(){return p?l(s(this).content):u.get(this)}}),p&&a(p,r),e.wrappers.HTMLTemplateElement=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.registerWrapper,o=window.HTMLMediaElement;o&&(t.prototype=Object.create(n.prototype),r(o,t,document.createElement("audio")),e.wrappers.HTMLMediaElement=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var t=i(document.createElement("audio"));r.call(this,t),a(t,this),t.setAttribute("preload","auto"),void 0!==e&&t.setAttribute("src",e)}var r=e.wrappers.HTMLMediaElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLAudioElement;s&&(t.prototype=Object.create(r.prototype),o(s,t,document.createElement("audio")),n.prototype=t.prototype,e.wrappers.HTMLAudioElement=t,e.wrappers.Audio=n)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e.replace(/\s+/g," ").trim()}function n(e){o.call(this,e)}function r(e,t,n,i){if(!(this instanceof r))throw new TypeError("DOM object constructor cannot be called as a function.");var a=c(document.createElement("option"));o.call(this,a),s(a,this),void 0!==e&&(a.text=e),void 0!==t&&a.setAttribute("value",t),n===!0&&a.setAttribute("selected",""),a.selected=i===!0}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.rewrap,c=e.unwrap,l=e.wrap,u=window.HTMLOptionElement;n.prototype=Object.create(o.prototype),i(n.prototype,{get text(){return t(this.textContent)},set text(e){this.textContent=t(String(e))},get form(){return l(c(this).form)}}),a(u,n,document.createElement("option")),r.prototype=n.prototype,e.wrappers.HTMLOptionElement=n,e.wrappers.Option=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=window.HTMLSelectElement;t.prototype=Object.create(n.prototype),r(t.prototype,{add:function(e,t){"object"==typeof t&&(t=i(t)),i(this).add(i(e),t)},remove:function(e){return void 0===e?void n.prototype.remove.call(this):("object"==typeof e&&(e=i(e)),void i(this).remove(e))},get form(){return a(i(this).form)}}),o(s,t,document.createElement("select")),e.wrappers.HTMLSelectElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=e.wrapHTMLCollection,c=window.HTMLTableElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get caption(){return a(i(this).caption)},createCaption:function(){return a(i(this).createCaption())},get tHead(){return a(i(this).tHead)},createTHead:function(){return a(i(this).createTHead())},createTFoot:function(){return a(i(this).createTFoot())},get tFoot(){return a(i(this).tFoot)},get tBodies(){return s(i(this).tBodies)},createTBody:function(){return a(i(this).createTBody())},get rows(){return s(i(this).rows)},insertRow:function(e){return a(i(this).insertRow(e))}}),o(c,t,document.createElement("table")),e.wrappers.HTMLTableElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableSectionElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get rows(){return i(a(this).rows)},insertRow:function(e){return s(a(this).insertRow(e))}}),o(c,t,document.createElement("thead")),e.wrappers.HTMLTableSectionElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableRowElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get cells(){return i(a(this).cells)},insertCell:function(e){return s(a(this).insertCell(e))}}),o(c,t,document.createElement("tr")),e.wrappers.HTMLTableRowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e.localName){case"content":return new n(e);case"shadow":return new o(e);case"template":return new i(e)}r.call(this,e)}var n=e.wrappers.HTMLContentElement,r=e.wrappers.HTMLElement,o=e.wrappers.HTMLShadowElement,i=e.wrappers.HTMLTemplateElement,a=(e.mixin,e.registerWrapper),s=window.HTMLUnknownElement;t.prototype=Object.create(r.prototype),a(s,t),e.wrappers.HTMLUnknownElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Element,r=e.wrappers.HTMLElement,o=e.registerWrapper,i=(e.defineWrapGetter,e.unsafeUnwrap),a=e.wrap,s=e.mixin,c="http://www.w3.org/2000/svg",l=window.SVGElement,u=document.createElementNS(c,"title");if(!("classList"in u)){var d=Object.getOwnPropertyDescriptor(n.prototype,"classList");Object.defineProperty(r.prototype,"classList",d),delete n.prototype.classList}t.prototype=Object.create(n.prototype),s(t.prototype,{get ownerSVGElement(){return a(i(this).ownerSVGElement)}}),o(l,t,document.createElementNS(c,"title")),e.wrappers.SVGElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){p.call(this,e)}var n=e.mixin,r=e.registerWrapper,o=e.unwrap,i=e.wrap,a=window.SVGUseElement,s="http://www.w3.org/2000/svg",c=i(document.createElementNS(s,"g")),l=document.createElementNS(s,"use"),u=c.constructor,d=Object.getPrototypeOf(u.prototype),p=d.constructor;t.prototype=Object.create(d),"instanceRoot"in l&&n(t.prototype,{get instanceRoot(){return i(o(this).instanceRoot)},get animatedInstanceRoot(){return i(o(this).animatedInstanceRoot)}}),r(a,t,l),e.wrappers.SVGUseElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.SVGElementInstance;s&&(t.prototype=Object.create(n.prototype),r(t.prototype,{get correspondingElement(){return a(i(this).correspondingElement)},get correspondingUseElement(){return a(i(this).correspondingUseElement)},get parentNode(){return a(i(this).parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return a(i(this).firstChild)},get lastChild(){return a(i(this).lastChild)},get previousSibling(){return a(i(this).previousSibling)},get nextSibling(){return a(i(this).nextSibling)}}),o(s,t),e.wrappers.SVGElementInstance=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){o(e,this)}var n=e.mixin,r=e.registerWrapper,o=e.setWrapper,i=e.unsafeUnwrap,a=e.unwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.CanvasRenderingContext2D;n(t.prototype,{get canvas(){return c(i(this).canvas)},drawImage:function(){arguments[0]=s(arguments[0]),i(this).drawImage.apply(i(this),arguments)},createPattern:function(){return arguments[0]=a(arguments[0]),i(this).createPattern.apply(i(this),arguments)}}),r(l,t,document.createElement("canvas").getContext("2d")),e.wrappers.CanvasRenderingContext2D=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){i(e,this)}var n=e.addForwardingProperties,r=e.mixin,o=e.registerWrapper,i=e.setWrapper,a=e.unsafeUnwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.WebGLRenderingContext;if(l){r(t.prototype,{get canvas(){return c(a(this).canvas)},texImage2D:function(){arguments[5]=s(arguments[5]),a(this).texImage2D.apply(a(this),arguments)},texSubImage2D:function(){arguments[6]=s(arguments[6]),a(this).texSubImage2D.apply(a(this),arguments)}});var u=Object.getPrototypeOf(l.prototype);u!==Object.prototype&&n(u,t.prototype);var d=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};o(l,t,d),e.wrappers.WebGLRenderingContext=t}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Node,r=e.GetElementsByInterface,o=e.NonElementParentNodeInterface,i=e.ParentNodeInterface,a=e.SelectorsInterface,s=e.mixin,c=e.registerObject,l=e.registerWrapper,u=window.DocumentFragment;t.prototype=Object.create(n.prototype),s(t.prototype,i),s(t.prototype,a),s(t.prototype,r),s(t.prototype,o),l(u,t,document.createDocumentFragment()),e.wrappers.DocumentFragment=t;var d=c(document.createComment(""));e.wrappers.Comment=d}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(u(e).ownerDocument.createDocumentFragment());n.call(this,t),c(t,this);var o=e.shadowRoot;f.set(this,o),this.treeScope_=new r(this,a(o||e)),h.set(this,e)}var n=e.wrappers.DocumentFragment,r=e.TreeScope,o=e.elementFromPoint,i=e.getInnerHTML,a=e.getTreeScope,s=e.mixin,c=e.rewrap,l=e.setInnerHTML,u=e.unsafeUnwrap,d=e.unwrap,p=e.wrap,h=new WeakMap,f=new WeakMap;t.prototype=Object.create(n.prototype),s(t.prototype,{constructor:t,get innerHTML(){return i(this)},set innerHTML(e){l(this,e),this.invalidateShadowRenderer()},get olderShadowRoot(){return f.get(this)||null},get host(){return h.get(this)||null},invalidateShadowRenderer:function(){return h.get(this).invalidateShadowRenderer()},elementFromPoint:function(e,t){return o(this,this.ownerDocument,e,t)},getSelection:function(){return document.getSelection()},get activeElement(){var e=d(this).ownerDocument.activeElement;if(!e||!e.nodeType)return null;for(var t=p(e);!this.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}}),e.wrappers.ShadowRoot=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(e).root;return t instanceof h?t.host:null}function n(t,n){if(t.shadowRoot){n=Math.min(t.childNodes.length-1,n);var r=t.childNodes[n];if(r){var o=e.getDestinationInsertionPoints(r);if(o.length>0){var i=o[0].parentNode;i.nodeType==Node.ELEMENT_NODE&&(t=i)}}}return t}function r(e){return e=u(e),t(e)||e}function o(e){a(e,this)}var i=e.registerWrapper,a=e.setWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.unwrapIfNeeded,u=e.wrap,d=e.getTreeScope,p=window.Range,h=e.wrappers.ShadowRoot;o.prototype={get startContainer(){return r(s(this).startContainer)},get endContainer(){return r(s(this).endContainer)},get commonAncestorContainer(){return r(s(this).commonAncestorContainer)},setStart:function(e,t){e=n(e,t),s(this).setStart(l(e),t)},setEnd:function(e,t){e=n(e,t),s(this).setEnd(l(e),t)},setStartBefore:function(e){s(this).setStartBefore(l(e))},setStartAfter:function(e){s(this).setStartAfter(l(e))},setEndBefore:function(e){s(this).setEndBefore(l(e))},setEndAfter:function(e){s(this).setEndAfter(l(e))},selectNode:function(e){s(this).selectNode(l(e))},selectNodeContents:function(e){s(this).selectNodeContents(l(e))},compareBoundaryPoints:function(e,t){return s(this).compareBoundaryPoints(e,c(t))},extractContents:function(){return u(s(this).extractContents())},cloneContents:function(){return u(s(this).cloneContents())},insertNode:function(e){s(this).insertNode(l(e))},surroundContents:function(e){s(this).surroundContents(l(e))},cloneRange:function(){return u(s(this).cloneRange())},isPointInRange:function(e,t){return s(this).isPointInRange(l(e),t)},comparePoint:function(e,t){return s(this).comparePoint(l(e),t)},intersectsNode:function(e){return s(this).intersectsNode(l(e))},toString:function(){return s(this).toString()}},p.prototype.createContextualFragment&&(o.prototype.createContextualFragment=function(e){return u(s(this).createContextualFragment(e))}),i(window.Range,o,document.createRange()),e.wrappers.Range=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.previousSibling_=e.previousSibling,e.nextSibling_=e.nextSibling,e.parentNode_=e.parentNode}function n(n,o,i){var a=x(n),s=x(o),c=i?x(i):null;if(r(o),t(o),i)n.firstChild===i&&(n.firstChild_=i),i.previousSibling_=i.previousSibling;else{n.lastChild_=n.lastChild,n.lastChild===n.firstChild&&(n.firstChild_=n.firstChild);var l=R(a.lastChild);l&&(l.nextSibling_=l.nextSibling)}e.originalInsertBefore.call(a,s,c)}function r(n){var r=x(n),o=r.parentNode;if(o){var i=R(o);t(n),n.previousSibling&&(n.previousSibling.nextSibling_=n),n.nextSibling&&(n.nextSibling.previousSibling_=n),i.lastChild===n&&(i.lastChild_=n),i.firstChild===n&&(i.firstChild_=n),e.originalRemoveChild.call(o,r)}}function o(e){P.set(e,[])}function i(e){var t=P.get(e);return t||P.set(e,t=[]),t}function a(e){for(var t=[],n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t}function s(){for(var e=0;e=0;o--){var i=r[o],a=m(i);if(a){var s=i.olderShadowRoot;s&&(n=f(s));for(var c=0;c=0;u--)l=Object.create(l);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(e){var t=o[e];t&&(l[e]=function(){j(this)instanceof r||O(this),t.apply(j(this),arguments)})});var d={prototype:l};i&&(d["extends"]=i),r.prototype=o,r.prototype.constructor=r,e.constructorTable.set(l,r),e.nativePrototypeTable.set(o,l);k.call(C(this),t,d);return r},E([window.HTMLDocument||window.Document],["registerElement"])}E([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"]),E([window.HTMLBodyElement,window.HTMLHeadElement,window.HTMLHtmlElement],_),E([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","createTreeWalker","elementFromPoint","getElementById","getElementsByName","getSelection"]),S(t.prototype,l),S(t.prototype,d),S(t.prototype,f),S(t.prototype,p),S(t.prototype,{get implementation(){var e=H.get(this);return e?e:(e=new a(C(this).implementation),H.set(this,e),e)},get defaultView(){return j(C(this).defaultView)}}),T(window.Document,t,document.implementation.createHTMLDocument("")),window.HTMLDocument&&T(window.HTMLDocument,t),D([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]);var A=document.implementation.createDocument;a.prototype.createDocument=function(){return arguments[2]=C(arguments[2]),j(A.apply(N(this),arguments))},s(a,"createDocumentType"),s(a,"createHTMLDocument"),c(a,"hasFeature"),T(window.DOMImplementation,a),E([window.DOMImplementation],["createDocument","createDocumentType","createHTMLDocument","hasFeature"]),e.adoptNodeNoRemove=r,e.wrappers.DOMImplementation=a,e.wrappers.Document=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.wrappers.Selection,o=e.mixin,i=e.registerWrapper,a=e.renderAllPending,s=e.unwrap,c=e.unwrapIfNeeded,l=e.wrap,u=window.Window,d=window.getComputedStyle,p=window.getDefaultComputedStyle,h=window.getSelection;t.prototype=Object.create(n.prototype),u.prototype.getComputedStyle=function(e,t){return l(this||window).getComputedStyle(c(e),t)},p&&(u.prototype.getDefaultComputedStyle=function(e,t){return l(this||window).getDefaultComputedStyle(c(e),t)}),u.prototype.getSelection=function(){return l(this||window).getSelection()},delete window.getComputedStyle,delete window.getDefaultComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(e){u.prototype[e]=function(){var t=l(this||window);return t[e].apply(t,arguments)},delete window[e]}),o(t.prototype,{getComputedStyle:function(e,t){return a(),d.call(s(this),c(e),t)},getSelection:function(){return a(),new r(h.call(s(this)))},get document(){return l(s(this).document)}}),p&&(t.prototype.getDefaultComputedStyle=function(e,t){return a(),p.call(s(this),c(e),t)}),i(u,t,window),e.wrappers.Window=t}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrap,n=window.DataTransfer||window.Clipboard,r=n.prototype.setDragImage;r&&(n.prototype.setDragImage=function(e,n,o){r.call(this,t(e),n,o)})}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t;t=e instanceof i?e:new i(e&&o(e)),r(t,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unwrap,i=window.FormData;i&&(n(i,t,new i),e.wrappers.FormData=t)}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrapIfNeeded,n=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.send=function(e){return n.call(this,t(e))}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=n[e],r=window[t];if(r){var o=document.createElement(e),i=o.constructor;window[t]=i}}var n=(e.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(n).forEach(t),Object.getOwnPropertyNames(e.wrappers).forEach(function(t){window[t]=e.wrappers[t]})}(window.ShadowDOMPolyfill),function(e){function t(e,t){var n="";return Array.prototype.forEach.call(e,function(e){n+=e.textContent+"\n\n"}),t||(n=n.replace(d,"")),n}function n(e){var t=document.createElement("style");return t.textContent=e,t}function r(e){var t=n(e);document.head.appendChild(t);var r=[];if(t.sheet)try{r=t.sheet.cssRules}catch(o){}else console.warn("sheet not found",t);return t.parentNode.removeChild(t),r}function o(){C.initialized=!0,document.body.appendChild(C);var e=C.contentDocument,t=e.createElement("base");t.href=document.baseURI,e.head.appendChild(t)}function i(e){C.initialized||o(),document.body.appendChild(C),e(C.contentDocument),document.body.removeChild(C)}function a(e,t){if(t){var o;if(e.match("@import")&&D){var a=n(e);i(function(e){e.head.appendChild(a.impl),o=Array.prototype.slice.call(a.sheet.cssRules,0),t(o)})}else o=r(e),t(o)}}function s(e){e&&l().appendChild(document.createTextNode(e))}function c(e,t){var r=n(e);r.setAttribute(t,""),r.setAttribute(x,""),document.head.appendChild(r)}function l(){return j||(j=document.createElement("style"),j.setAttribute(x,""),j[x]=!0),j}var u={strictStyling:!1,registry:{},shimStyling:function(e,n,r){var o=this.prepareRoot(e,n,r),i=this.isTypeExtension(r),a=this.makeScopeSelector(n,i),s=t(o,!0);s=this.scopeCssText(s,a),e&&(e.shimmedStyle=s),this.addCssToDocument(s,n)},shimStyle:function(e,t){return this.shimCssText(e.textContent,t)},shimCssText:function(e,t){return e=this.insertDirectives(e),this.scopeCssText(e,t)},makeScopeSelector:function(e,t){return e?t?"[is="+e+"]":e:""},isTypeExtension:function(e){return e&&e.indexOf("-")<0},prepareRoot:function(e,t,n){var r=this.registerRoot(e,t,n);return this.replaceTextInStyles(r.rootStyles,this.insertDirectives),this.removeStyles(e,r.rootStyles),this.strictStyling&&this.applyScopeToContent(e,t),r.scopeStyles},removeStyles:function(e,t){for(var n,r=0,o=t.length;r","+","~"],r=e,o="["+t+"]";return n.forEach(function(e){var t=r.split(e);r=t.map(function(e){var t=e.trim().replace(L,"");return t&&n.indexOf(t)<0&&t.indexOf(o)<0&&(e=t.replace(/([^:]*)(:*)(.*)/,"$1"+o+"$2$3")),e}).join(e)}),r},insertPolyfillHostInCssText:function(e){return e.replace(M,b).replace(T,g)},propertiesFromRule:function(e){var t=e.style.cssText;e.style.content&&!e.style.content.match(/['"]+|attr/)&&(t=t.replace(/content:[^;]*;/g,"content: '"+e.style.content+"';"));var n=e.style;for(var r in n)"initial"===n[r]&&(t+=r+": initial; ");return t},replaceTextInStyles:function(e,t){e&&t&&(e instanceof Array||(e=[e]),Array.prototype.forEach.call(e,function(e){e.textContent=t.call(this,e.textContent)},this))},addCssToDocument:function(e,t){e.match("@import")?c(e,t):s(e)}},d=/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,p=/\/\*\s*@polyfill ([^*]*\*+([^\/*][^*]*\*+)*\/)([^{]*?){/gim,h=/polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim,f=/\/\*\s@polyfill-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,m=/(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,w=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,v=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,g="-shadowcsshost",b="-shadowcsscontext",y=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)",E=new RegExp("("+g+y,"gim"),_=new RegExp("("+b+y,"gim"),S="([>\\s~+[.,{:][\\s\\S]*)?$",T=/\:host/gim,M=/\:host-context/gim,O=g+"-no-combinator",L=new RegExp(g,"gim"),N=(new RegExp(b,"gim"),[/>>>/g,/::shadow/g,/::content/g,/\/deep\//g,/\/shadow\//g,/\/shadow-deep\//g,/\^\^/g,/\^(?!=)/g]),C=document.createElement("iframe");C.style.display="none";var j,D=navigator.userAgent.match("Chrome"),H="shim-shadowdom",x="shim-shadowdom-css",R="no-shim";if(window.ShadowDOMPolyfill){s("style { display: none !important; }\n");var I=ShadowDOMPolyfill.wrap(document),P=I.querySelector("head");P.insertBefore(l(),P.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){e.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var t="link[rel=stylesheet]["+H+"]",n="style["+H+"]";HTMLImports.importer.documentPreloadSelectors+=","+t,HTMLImports.importer.importsPreloadSelectors+=","+t,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,t,n].join(",");var r=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(e){if(!e[x]){var t=e.__importElement||e;if(!t.hasAttribute(H))return void r.call(this,e);e.__resource&&(t=e.ownerDocument.createElement("style"),t.textContent=e.__resource),HTMLImports.path.resolveUrlsInStyle(t,e.href),t.textContent=u.shimStyle(t),t.removeAttribute(H,""),t.setAttribute(x,""),t[x]=!0,t.parentNode!==P&&(e.parentNode===P?P.replaceChild(t,e):this.addElementToDocument(t)),t.__importParsed=!0,this.markParsingComplete(e),this.parseNext()}};var o=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(e){return"link"===e.localName&&"stylesheet"===e.rel&&e.hasAttribute(H)?e.__resource:o.call(this,e)}}})}e.ShadowCSS=u}(window.WebComponents)),function(e){window.ShadowDOMPolyfill?(window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}}(window.WebComponents),function(e){"use strict";function t(e){return void 0!==p[e]}function n(){s.call(this),this._isInvalid=!0}function r(e){return""==e&&n.call(this),e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,63,96].indexOf(t)==-1?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,96].indexOf(t)==-1?e:encodeURIComponent(e)}function a(e,a,s){function c(e){b.push(e)}var l=a||"scheme start",u=0,d="",v=!1,g=!1,b=[];e:for(;(e[u-1]!=f||0==u)&&!this._isInvalid;){var y=e[u];switch(l){case"scheme start":if(!y||!m.test(y)){if(a){c("Invalid scheme.");break e}d="",l="no scheme";continue}d+=y.toLowerCase(),l="scheme";break;case"scheme":if(y&&w.test(y))d+=y.toLowerCase();else{if(":"!=y){if(a){if(f==y)break e;c("Code point not allowed in scheme: "+y);break e}d="",u=0,l="no scheme";continue}if(this._scheme=d,d="",a)break e;t(this._scheme)&&(this._isRelative=!0),l="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==y?(this._query="?",l="query"):"#"==y?(this._fragment="#",l="fragment"):f!=y&&"\t"!=y&&"\n"!=y&&"\r"!=y&&(this._schemeData+=o(y));break;case"no scheme":if(s&&t(s._scheme)){l="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=y||"/"!=e[u+1]){c("Expected /, got: "+y),l="relative";continue}l="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),f==y){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==y||"\\"==y)"\\"==y&&c("\\ is an invalid code point."),l="relative slash";else if("?"==y)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,l="query";else{if("#"!=y){var E=e[u+1],_=e[u+2];("file"!=this._scheme||!m.test(y)||":"!=E&&"|"!=E||f!=_&&"/"!=_&&"\\"!=_&&"?"!=_&&"#"!=_)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),l="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,l="fragment"}break;case"relative slash":if("/"!=y&&"\\"!=y){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),l="relative path";continue}"\\"==y&&c("\\ is an invalid code point."),l="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=y){c("Expected '/', got: "+y),l="authority ignore slashes";continue}l="authority second slash";break;case"authority second slash":if(l="authority ignore slashes","/"!=y){c("Expected '/', got: "+y);continue}break;case"authority ignore slashes":if("/"!=y&&"\\"!=y){l="authority";continue}c("Expected authority, got: "+y);break;case"authority":if("@"==y){v&&(c("@ already seen."),d+="%40"),v=!0;for(var S=0;S0){var o=n[r-1],i=h(o,e);if(i)return void(n[r-1]=i)}else t(this.observer);n[r]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=w.get(e);t||w.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=w.get(e),n=0;n=200&&e.status<300||304===e.status||0===e.status},load:function(n,r,o){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}r.call(o,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,r=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};r.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,r=e.length;n-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,r,null,a)}.bind(this),0)}else{var s=function(t,n,o){this.receive(e,r,t,n,o)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,r,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,r,o){this.cache[e]=r;for(var i,a=this.pending[e],s=0,c=a.length;s=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,r=function(o){e.removeEventListener("load",r),e.removeEventListener("error",r),t&&t(o),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",r),e.addEventListener("error",r),l&&"style"===e.localName){var o=!1;if(e.textContent.indexOf("@import")==-1)o=!0;else if(e.sheet){o=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;c=0},hasResource:function(e){return!t(e)||void 0!==e.__doc}};e.parser=p,e.IMPORT_SELECTOR=d}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function r(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function o(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var o=n.createElement("base");o.setAttribute("href",t),n.baseURI||r(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(o),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,l=e.Loader,u=e.Observer,d=e.parser,p={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){h.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);h.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,r,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=r,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:o(r,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}d.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),d.parseNext()},loadedAll:function(){d.parseNext()}},h=new l(p.loaded.bind(p),p.loadedAll.bind(p));if(p.observer=new u,!document.baseURI){var f={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",f),Object.defineProperty(c,"baseURI",f)}e.importer=p,e.importLoader=h}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,r={added:function(e){for(var r,o,i,a,s=0,c=e.length;s=0)){n.push(e);for(var r,o=e.querySelectorAll("link[rel="+a+"]"),s=0,c=o.length;s=0&&b(r,HTMLElement),r)}function f(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return v(e),e}}var m,w=(e.isIE,e.upgradeDocumentTree),v=e.upgradeAll,g=e.upgradeWithDefinition,b=e.implementPrototype,y=e.useNative,E=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],_={},S="http://www.w3.org/1999/xhtml",T=document.createElement.bind(document),M=document.createElementNS.bind(document);m=Object.__proto__||y?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},f(Node.prototype,"cloneNode"),f(document,"importNode"),document.registerElement=t,document.createElement=h,document.createElementNS=p,e.registry=_,e["instanceof"]=m,e.reservedTagList=E,e.getRegisteredDefinition=l,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,r=e.initializeModules;e.isIE;if(n){var o=function(){};e.watchShadow=o,e.upgrade=o,e.upgradeAll=o,e.upgradeDocumentTree=o,e.upgradeSubtree=o,e.takeRecords=o,e["instanceof"]=function(e,t){return e instanceof t}}else r();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){Function.prototype.bind||(Function.prototype.bind=function(e){var t=this,n=Array.prototype.slice.call(arguments,1);return function(){var r=n.slice();return r.push.apply(r,arguments),t.apply(e,r)}})}(window.WebComponents),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents),function(e){window.Platform=e}(window.WebComponents); \ No newline at end of file diff --git a/src/bootstrap.bash b/src/bootstrap.bash index 88c080a948..4038eaf942 100755 --- a/src/bootstrap.bash +++ b/src/bootstrap.bash @@ -96,7 +96,7 @@ if [ "$BOOTSTRAP_FORMAT" = "mintgz" ]; then echo "Preparing to generate build system's ${OUTGZ}; cleaning ..." rm -rf bin/gofmt rm -rf src/runtime/race/race_*.syso - rm -rf api test doc misc/cgo/test misc/trace + rm -rf api test doc misc/cgo/test rm -rf pkg/tool/*_*/{addr2line,api,cgo,cover,doc,fix,nm,objdump,pack,pprof,test2json,trace,vet} rm -rf pkg/*_*/{image,database,cmd} rm -rf $(find . -type d -name testdata) diff --git a/src/cmd/trace/static/README.md b/src/cmd/trace/static/README.md new file mode 100644 index 0000000000..f81c59eae5 --- /dev/null +++ b/src/cmd/trace/static/README.md @@ -0,0 +1,105 @@ +## Resources for Go's trace viewer + +Go execution trace UI (`go tool trace`) embeds +Chrome's trace viewer (Catapult) following the +[instructions]( +https://chromium.googlesource.com/catapult/+/refs/heads/master/tracing/docs/embedding-trace-viewer.md). This directory contains +the helper files to embed Chrome's trace viewer. + +The current resources were generated/copied from +[`Catapult@9508452e18f130c98499cb4c4f1e1efaedee8962`]( +https://chromium.googlesource.com/catapult/+/9508452e18f130c98499cb4c4f1e1efaedee8962). + +### Updating `trace_viewer_full.html` + +The file was generated by catapult's `vulcanize_trace_viewer` command. +``` +$ git clone https://chromium.googlesource.com/catapult +$ cd catapult +$ ./tracing/bin/vulcanize_trace_viewer --config=full +$ cp tracing/bin/trace_viewer_full.html $GOROOT/src/cmd/trace/static/trace_viewer_full.html +``` + +We are supposed to use --config=lean (produces smaller html), +but it is broken at the moment: +https://github.com/catapult-project/catapult/issues/2247 + +### Updating `webcomponents.min.js` + +`webcomponents.min.js` is necessary to let the trace viewer page +to import the `trace_viewer_full.html`. +This is copied from the catapult repo. + +``` +$ cp third_party/polymer/components/webcomponentsjs/webcomponents.min.js $GOROOT/src/cmd/trace/static/webcomponents.min.js +``` + +## Licenses + +The license for trace-viewer is as follows: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The license for webcomponents.min.js is as follows: + +/** + * @license + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ +// Copyright (c) 2014 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/cmd/trace/static/trace_viewer_full.html b/src/cmd/trace/static/trace_viewer_full.html new file mode 100644 index 0000000000..ae6e35fca2 --- /dev/null +++ b/src/cmd/trace/static/trace_viewer_full.html @@ -0,0 +1,10441 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cmd/trace/static/webcomponents.min.js b/src/cmd/trace/static/webcomponents.min.js new file mode 100644 index 0000000000..ad8196bc30 --- /dev/null +++ b/src/cmd/trace/static/webcomponents.min.js @@ -0,0 +1,14 @@ +/** + * @license + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ +// @version 0.7.24 +!function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomponents.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOpts){if(location.search.slice(1).split("&").forEach(function(e){var t,r=e.split("=");r[0]&&(t=r[0].match(/wc-(.+)/))&&(n[t[1]]=r[1]||!0)}),t)for(var r,o=0;r=t.attributes[o];o++)"src"!==r.name&&(n[r.name]=r.value||!0);if(n.log&&n.log.split){var i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={}}n.shadow=n.shadow||n.shadowdom||n.polyfill,"native"===n.shadow?n.shadow=!1:n.shadow=n.shadow||!HTMLElement.prototype.createShadowRoot,n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=n.register),WebComponents.flags=n}(),WebComponents.flags.shadow&&("undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:function(t,n){var r=t[this.name];return r&&r[0]===t?r[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=n}(),window.ShadowDOMPolyfill={},function(e){"use strict";function t(){if("undefined"!=typeof chrome&&chrome.app&&chrome.app.runtime)return!1;if(navigator.getDeviceStorage)return!1;try{var e=new Function("return true;");return e()}catch(t){return!1}}function n(e){if(!e)throw new Error("Assertion failed")}function r(e,t){for(var n=W(t),r=0;r0||n>0;)if(0!=t)if(0!=n){var l,u=e[t-1][n-1],d=e[t-1][n],p=e[t][n-1];l=d0){for(var u=0;u0&&r.length>0;){var i=n.pop(),a=r.pop();if(i!==a)break;o=i}return o}function u(e,t,n){t instanceof G.Window&&(t=t.document);var o,i=A(t),a=A(n),s=r(n,e),o=l(i,a);o||(o=a.root);for(var c=o;c;c=c.parent)for(var u=0;u0;i--)if(!g(t[i],e,o,t,r))return!1;return!0}function w(e,t,n,r){var o=ie,i=t[0]||n;return g(i,e,o,t,r)}function v(e,t,n,r){for(var o=ae,i=1;i0&&g(n,e,o,t,r)}function g(e,t,n,r,o){var i=z.get(e);if(!i)return!0;var a=o||s(r,e);if(a===e){if(n===oe)return!0;n===ae&&(n=ie)}else if(n===ae&&!t.bubbles)return!0;if("relatedTarget"in t){var c=B(t),l=c.relatedTarget;if(l){if(l instanceof Object&&l.addEventListener){var d=V(l),p=u(t,e,d);if(p===a)return!0}else p=null;Z.set(t,p)}}J.set(t,n);var h=t.type,f=!1;X.set(t,a),Y.set(t,e),i.depth++;for(var m=0,w=i.length;m=0;a--)e.removeChild(i[a]),i[a].parentNode_=t;U=!1;for(var a=0;a>>/g," ")}function r(e){return String(e).replace(/:host\(([^\s]+)\)/g,"$1").replace(/([^\s]):host/g,"$1").replace(":host","*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content|>>>/g," ")}function o(e,t){for(var n,r=e.firstElementChild;r;){if(r.matches(t))return r;if(n=o(r,t))return n;r=r.nextElementSibling}return null}function i(e,t){return e.matches(t)}function a(e,t,n){var r=e.localName;return r===t||r===n&&e.namespaceURI===j}function s(){return!0}function c(e,t,n){return e.localName===n}function l(e,t){return e.namespaceURI===t}function u(e,t,n){return e.namespaceURI===t&&e.localName===n}function d(e,t,n,r,o,i){for(var a=e.firstElementChild;a;)r(a,o,i)&&(n[t++]=a),t=d(a,t,n,r,o,i),a=a.nextElementSibling;return t}function p(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,null);if(c instanceof N)s=S.call(c,i);else{if(!(c instanceof C))return d(this,r,o,n,i,null);s=_.call(c,i)}return t(s,r,o,a)}function h(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=M.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=T.call(c,i,a)}return t(s,r,o,!1)}function f(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=L.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=O.call(c,i,a)}return t(s,r,o,!1)}var m=e.wrappers.HTMLCollection,w=e.wrappers.NodeList,v=e.getTreeScope,g=e.unsafeUnwrap,b=e.wrap,y=document.querySelector,E=document.documentElement.querySelector,_=document.querySelectorAll,S=document.documentElement.querySelectorAll,T=document.getElementsByTagName,M=document.documentElement.getElementsByTagName,O=document.getElementsByTagNameNS,L=document.documentElement.getElementsByTagNameNS,N=window.Element,C=window.HTMLDocument||window.Document,j="http://www.w3.org/1999/xhtml",D={ +querySelector:function(t){var r=n(t),i=r!==t;t=r;var a,s=g(this),c=v(this).root;if(c instanceof e.wrappers.ShadowRoot)return o(this,t);if(s instanceof N)a=b(E.call(s,t));else{if(!(s instanceof C))return o(this,t);a=b(y.call(s,t))}return a&&!i&&(c=v(a).root)&&c instanceof e.wrappers.ShadowRoot?o(this,t):a},querySelectorAll:function(e){var t=n(e),r=t!==e;e=t;var o=new w;return o.length=p.call(this,i,0,o,e,r),o}},H={matches:function(t){return t=r(t),e.originalMatches.call(g(this),t)}},x={getElementsByTagName:function(e){var t=new m,n="*"===e?s:a;return t.length=h.call(this,n,0,t,e,e.toLowerCase()),t},getElementsByClassName:function(e){return this.querySelectorAll("."+e)},getElementsByTagNameNS:function(e,t){var n=new m,r=null;return r="*"===e?"*"===t?s:c:"*"===t?l:u,n.length=f.call(this,r,0,n,e||null,t),n}};e.GetElementsByInterface=x,e.SelectorsInterface=D,e.MatchesInterface=H}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;return e}function n(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.previousSibling;return e}var r=e.wrappers.NodeList,o={get firstElementChild(){return t(this.firstChild)},get lastElementChild(){return n(this.lastChild)},get childElementCount(){for(var e=0,t=this.firstElementChild;t;t=t.nextElementSibling)e++;return e},get children(){for(var e=new r,t=0,n=this.firstElementChild;n;n=n.nextElementSibling)e[t++]=n;return e.length=t,e},remove:function(){var e=this.parentNode;e&&e.removeChild(this)}},i={get nextElementSibling(){return t(this.nextSibling)},get previousElementSibling(){return n(this.previousSibling)}},a={getElementById:function(e){return/[ \t\n\r\f]/.test(e)?null:this.querySelector('[id="'+e+'"]')}};e.ChildNodeInterface=i,e.NonElementParentNodeInterface=a,e.ParentNodeInterface=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}var n=e.ChildNodeInterface,r=e.wrappers.Node,o=e.enqueueMutation,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=window.CharacterData;t.prototype=Object.create(r.prototype),i(t.prototype,{get nodeValue(){return this.data},set nodeValue(e){this.data=e},get textContent(){return this.data},set textContent(e){this.data=e},get data(){return s(this).data},set data(e){var t=s(this).data;o(this,"characterData",{oldValue:t}),s(this).data=e}}),i(t.prototype,n),a(c,t,document.createTextNode("")),e.wrappers.CharacterData=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e>>>0}function n(e){r.call(this,e)}var r=e.wrappers.CharacterData,o=(e.enqueueMutation,e.mixin),i=e.registerWrapper,a=window.Text;n.prototype=Object.create(r.prototype),o(n.prototype,{splitText:function(e){e=t(e);var n=this.data;if(e>n.length)throw new Error("IndexSizeError");var r=n.slice(0,e),o=n.slice(e);this.data=r;var i=this.ownerDocument.createTextNode(o);return this.parentNode&&this.parentNode.insertBefore(i,this.nextSibling),i}}),i(a,n,document.createTextNode("")),e.wrappers.Text=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return i(e).getAttribute("class")}function n(e,t){a(e,"attributes",{name:"class",namespace:null,oldValue:t})}function r(t){e.invalidateRendererBasedOnAttribute(t,"class")}function o(e,o,i){var a=e.ownerElement_;if(null==a)return o.apply(e,i);var s=t(a),c=o.apply(e,i);return t(a)!==s&&(n(a,s),r(a)),c}if(!window.DOMTokenList)return void console.warn("Missing DOMTokenList prototype, please include a compatible classList polyfill such as http://goo.gl/uTcepH.");var i=e.unsafeUnwrap,a=e.enqueueMutation,s=DOMTokenList.prototype.add;DOMTokenList.prototype.add=function(){o(this,s,arguments)};var c=DOMTokenList.prototype.remove;DOMTokenList.prototype.remove=function(){o(this,c,arguments)};var l=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(){return o(this,l,arguments)}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n){var r=t.parentNode;if(r&&r.shadowRoot){var o=e.getRendererForHost(r);o.dependsOnAttribute(n)&&o.invalidate()}}function n(e,t,n){u(e,"attributes",{name:t,namespace:null,oldValue:n})}function r(e){a.call(this,e)}var o=e.ChildNodeInterface,i=e.GetElementsByInterface,a=e.wrappers.Node,s=e.ParentNodeInterface,c=e.SelectorsInterface,l=e.MatchesInterface,u=(e.addWrapNodeListMethod,e.enqueueMutation),d=e.mixin,p=(e.oneOf,e.registerWrapper),h=e.unsafeUnwrap,f=e.wrappers,m=window.Element,w=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(e){return m.prototype[e]}),v=w[0],g=m.prototype[v],b=new WeakMap;r.prototype=Object.create(a.prototype),d(r.prototype,{createShadowRoot:function(){var t=new f.ShadowRoot(this);h(this).polymerShadowRoot_=t;var n=e.getRendererForHost(this);return n.invalidate(),t},get shadowRoot(){return h(this).polymerShadowRoot_||null},setAttribute:function(e,r){var o=h(this).getAttribute(e);h(this).setAttribute(e,r),n(this,e,o),t(this,e)},removeAttribute:function(e){var r=h(this).getAttribute(e);h(this).removeAttribute(e),n(this,e,r),t(this,e)},get classList(){var e=b.get(this);if(!e){if(e=h(this).classList,!e)return;e.ownerElement_=this,b.set(this,e)}return e},get className(){return h(this).className},set className(e){this.setAttribute("class",e)},get id(){return h(this).id},set id(e){this.setAttribute("id",e)}}),w.forEach(function(e){"matches"!==e&&(r.prototype[e]=function(e){return this.matches(e)})}),m.prototype.webkitCreateShadowRoot&&(r.prototype.webkitCreateShadowRoot=r.prototype.createShadowRoot),d(r.prototype,o),d(r.prototype,i),d(r.prototype,s),d(r.prototype,c),d(r.prototype,l),p(m,r,document.createElementNS(null,"x")),e.invalidateRendererBasedOnAttribute=t,e.matchesNames=w,e.originalMatches=g,e.wrappers.Element=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";case" ":return" "}}function n(e){return e.replace(L,t)}function r(e){return e.replace(N,t)}function o(e){for(var t={},n=0;n"):c+">"+s(e)+"";case Node.TEXT_NODE:var d=e.data;return t&&j[t.localName]?d:r(d);case Node.COMMENT_NODE:return"";default:throw console.error(e),new Error("not implemented")}}function s(e){e instanceof O.HTMLTemplateElement&&(e=e.content);for(var t="",n=e.firstChild;n;n=n.nextSibling)t+=a(n,e);return t}function c(e,t,n){var r=n||"div";e.textContent="";var o=T(e.ownerDocument.createElement(r));o.innerHTML=t;for(var i;i=o.firstChild;)e.appendChild(M(i))}function l(e){m.call(this,e)}function u(e,t){var n=T(e.cloneNode(!1));n.innerHTML=t;for(var r,o=T(document.createDocumentFragment());r=n.firstChild;)o.appendChild(r);return M(o)}function d(t){return function(){return e.renderAllPending(),S(this)[t]}}function p(e){w(l,e,d(e))}function h(t){Object.defineProperty(l.prototype,t,{get:d(t),set:function(n){e.renderAllPending(),S(this)[t]=n},configurable:!0,enumerable:!0})}function f(t){Object.defineProperty(l.prototype,t,{value:function(){return e.renderAllPending(),S(this)[t].apply(S(this),arguments)},configurable:!0,enumerable:!0})}var m=e.wrappers.Element,w=e.defineGetter,v=e.enqueueMutation,g=e.mixin,b=e.nodesWereAdded,y=e.nodesWereRemoved,E=e.registerWrapper,_=e.snapshotNodeList,S=e.unsafeUnwrap,T=e.unwrap,M=e.wrap,O=e.wrappers,L=/[&\u00A0"]/g,N=/[&\u00A0<>]/g,C=o(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),j=o(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D="http://www.w3.org/1999/xhtml",H=/MSIE/.test(navigator.userAgent),x=window.HTMLElement,R=window.HTMLTemplateElement;l.prototype=Object.create(m.prototype),g(l.prototype,{get innerHTML(){return s(this)},set innerHTML(e){if(H&&j[this.localName])return void(this.textContent=e);var t=_(this.childNodes);this.invalidateShadowRenderer()?this instanceof O.HTMLTemplateElement?c(this.content,e):c(this,e,this.tagName):!R&&this instanceof O.HTMLTemplateElement?c(this.content,e):S(this).innerHTML=e;var n=_(this.childNodes);v(this,"childList",{addedNodes:n,removedNodes:t}),y(t),b(n,this)},get outerHTML(){return a(this,this.parentNode)},set outerHTML(e){var t=this.parentNode;if(t){t.invalidateShadowRenderer();var n=u(t,e);t.replaceChild(n,this)}},insertAdjacentHTML:function(e,t){var n,r;switch(String(e).toLowerCase()){case"beforebegin":n=this.parentNode,r=this;break;case"afterend":n=this.parentNode,r=this.nextSibling;break;case"afterbegin":n=this,r=this.firstChild;break;case"beforeend":n=this,r=null;break;default:return}var o=u(n,t);n.insertBefore(o,r)},get hidden(){return this.hasAttribute("hidden")},set hidden(e){e?this.setAttribute("hidden",""):this.removeAttribute("hidden")}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(p),["scrollLeft","scrollTop"].forEach(h),["focus","getBoundingClientRect","getClientRects","scrollIntoView"].forEach(f),E(x,l,document.createElement("b")),e.wrappers.HTMLElement=l,e.getInnerHTML=s,e.setInnerHTML=c}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.HTMLCanvasElement;t.prototype=Object.create(n.prototype),r(t.prototype,{getContext:function(){var e=i(this).getContext.apply(i(this),arguments);return e&&a(e)}}),o(s,t,document.createElement("canvas")),e.wrappers.HTMLCanvasElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=window.HTMLContentElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get select(){return this.getAttribute("select")},set select(e){this.setAttribute("select",e)},setAttribute:function(e,t){n.prototype.setAttribute.call(this,e,t),"select"===String(e).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),i&&o(i,t),e.wrappers.HTMLContentElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=window.HTMLFormElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get elements(){return i(a(this).elements)}}),o(s,t,document.createElement("form")),e.wrappers.HTMLFormElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e,t){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var o=i(document.createElement("img"));r.call(this,o),a(o,this),void 0!==e&&(o.width=e),void 0!==t&&(o.height=t)}var r=e.wrappers.HTMLElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLImageElement;t.prototype=Object.create(r.prototype),o(s,t,document.createElement("img")),n.prototype=t.prototype,e.wrappers.HTMLImageElement=t,e.wrappers.Image=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=(e.mixin,e.wrappers.NodeList,e.registerWrapper),o=window.HTMLShadowElement;t.prototype=Object.create(n.prototype),t.prototype.constructor=t,o&&r(o,t),e.wrappers.HTMLShadowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){if(!e.defaultView)return e;var t=d.get(e);if(!t){for(t=e.implementation.createHTMLDocument("");t.lastChild;)t.removeChild(t.lastChild);d.set(e,t)}return t}function n(e){for(var n,r=t(e.ownerDocument),o=c(r.createDocumentFragment());n=e.firstChild;)o.appendChild(n);return o}function r(e){if(o.call(this,e),!p){var t=n(e);u.set(this,l(t))}}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.wrap,u=new WeakMap,d=new WeakMap,p=window.HTMLTemplateElement;r.prototype=Object.create(o.prototype),i(r.prototype,{constructor:r,get content(){return p?l(s(this).content):u.get(this)}}),p&&a(p,r),e.wrappers.HTMLTemplateElement=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.registerWrapper,o=window.HTMLMediaElement;o&&(t.prototype=Object.create(n.prototype),r(o,t,document.createElement("audio")),e.wrappers.HTMLMediaElement=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var t=i(document.createElement("audio"));r.call(this,t),a(t,this),t.setAttribute("preload","auto"),void 0!==e&&t.setAttribute("src",e)}var r=e.wrappers.HTMLMediaElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLAudioElement;s&&(t.prototype=Object.create(r.prototype),o(s,t,document.createElement("audio")),n.prototype=t.prototype,e.wrappers.HTMLAudioElement=t,e.wrappers.Audio=n)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e.replace(/\s+/g," ").trim()}function n(e){o.call(this,e)}function r(e,t,n,i){if(!(this instanceof r))throw new TypeError("DOM object constructor cannot be called as a function.");var a=c(document.createElement("option"));o.call(this,a),s(a,this),void 0!==e&&(a.text=e),void 0!==t&&a.setAttribute("value",t),n===!0&&a.setAttribute("selected",""),a.selected=i===!0}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.rewrap,c=e.unwrap,l=e.wrap,u=window.HTMLOptionElement;n.prototype=Object.create(o.prototype),i(n.prototype,{get text(){return t(this.textContent)},set text(e){this.textContent=t(String(e))},get form(){return l(c(this).form)}}),a(u,n,document.createElement("option")),r.prototype=n.prototype,e.wrappers.HTMLOptionElement=n,e.wrappers.Option=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=window.HTMLSelectElement;t.prototype=Object.create(n.prototype),r(t.prototype,{add:function(e,t){"object"==typeof t&&(t=i(t)),i(this).add(i(e),t)},remove:function(e){return void 0===e?void n.prototype.remove.call(this):("object"==typeof e&&(e=i(e)),void i(this).remove(e))},get form(){return a(i(this).form)}}),o(s,t,document.createElement("select")),e.wrappers.HTMLSelectElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=e.wrapHTMLCollection,c=window.HTMLTableElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get caption(){return a(i(this).caption)},createCaption:function(){return a(i(this).createCaption())},get tHead(){return a(i(this).tHead)},createTHead:function(){return a(i(this).createTHead())},createTFoot:function(){return a(i(this).createTFoot())},get tFoot(){return a(i(this).tFoot)},get tBodies(){return s(i(this).tBodies)},createTBody:function(){return a(i(this).createTBody())},get rows(){return s(i(this).rows)},insertRow:function(e){return a(i(this).insertRow(e))}}),o(c,t,document.createElement("table")),e.wrappers.HTMLTableElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableSectionElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get rows(){return i(a(this).rows)},insertRow:function(e){return s(a(this).insertRow(e))}}),o(c,t,document.createElement("thead")),e.wrappers.HTMLTableSectionElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableRowElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get cells(){return i(a(this).cells)},insertCell:function(e){return s(a(this).insertCell(e))}}),o(c,t,document.createElement("tr")),e.wrappers.HTMLTableRowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e.localName){case"content":return new n(e);case"shadow":return new o(e);case"template":return new i(e)}r.call(this,e)}var n=e.wrappers.HTMLContentElement,r=e.wrappers.HTMLElement,o=e.wrappers.HTMLShadowElement,i=e.wrappers.HTMLTemplateElement,a=(e.mixin,e.registerWrapper),s=window.HTMLUnknownElement;t.prototype=Object.create(r.prototype),a(s,t),e.wrappers.HTMLUnknownElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Element,r=e.wrappers.HTMLElement,o=e.registerWrapper,i=(e.defineWrapGetter,e.unsafeUnwrap),a=e.wrap,s=e.mixin,c="http://www.w3.org/2000/svg",l=window.SVGElement,u=document.createElementNS(c,"title");if(!("classList"in u)){var d=Object.getOwnPropertyDescriptor(n.prototype,"classList");Object.defineProperty(r.prototype,"classList",d),delete n.prototype.classList}t.prototype=Object.create(n.prototype),s(t.prototype,{get ownerSVGElement(){return a(i(this).ownerSVGElement)}}),o(l,t,document.createElementNS(c,"title")),e.wrappers.SVGElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){p.call(this,e)}var n=e.mixin,r=e.registerWrapper,o=e.unwrap,i=e.wrap,a=window.SVGUseElement,s="http://www.w3.org/2000/svg",c=i(document.createElementNS(s,"g")),l=document.createElementNS(s,"use"),u=c.constructor,d=Object.getPrototypeOf(u.prototype),p=d.constructor;t.prototype=Object.create(d),"instanceRoot"in l&&n(t.prototype,{get instanceRoot(){return i(o(this).instanceRoot)},get animatedInstanceRoot(){return i(o(this).animatedInstanceRoot)}}),r(a,t,l),e.wrappers.SVGUseElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.SVGElementInstance;s&&(t.prototype=Object.create(n.prototype),r(t.prototype,{get correspondingElement(){return a(i(this).correspondingElement)},get correspondingUseElement(){return a(i(this).correspondingUseElement)},get parentNode(){return a(i(this).parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return a(i(this).firstChild)},get lastChild(){return a(i(this).lastChild)},get previousSibling(){return a(i(this).previousSibling)},get nextSibling(){return a(i(this).nextSibling)}}),o(s,t),e.wrappers.SVGElementInstance=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){o(e,this)}var n=e.mixin,r=e.registerWrapper,o=e.setWrapper,i=e.unsafeUnwrap,a=e.unwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.CanvasRenderingContext2D;n(t.prototype,{get canvas(){return c(i(this).canvas)},drawImage:function(){arguments[0]=s(arguments[0]),i(this).drawImage.apply(i(this),arguments)},createPattern:function(){return arguments[0]=a(arguments[0]),i(this).createPattern.apply(i(this),arguments)}}),r(l,t,document.createElement("canvas").getContext("2d")),e.wrappers.CanvasRenderingContext2D=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){i(e,this)}var n=e.addForwardingProperties,r=e.mixin,o=e.registerWrapper,i=e.setWrapper,a=e.unsafeUnwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.WebGLRenderingContext;if(l){r(t.prototype,{get canvas(){return c(a(this).canvas)},texImage2D:function(){arguments[5]=s(arguments[5]),a(this).texImage2D.apply(a(this),arguments)},texSubImage2D:function(){arguments[6]=s(arguments[6]),a(this).texSubImage2D.apply(a(this),arguments)}});var u=Object.getPrototypeOf(l.prototype);u!==Object.prototype&&n(u,t.prototype);var d=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};o(l,t,d),e.wrappers.WebGLRenderingContext=t}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Node,r=e.GetElementsByInterface,o=e.NonElementParentNodeInterface,i=e.ParentNodeInterface,a=e.SelectorsInterface,s=e.mixin,c=e.registerObject,l=e.registerWrapper,u=window.DocumentFragment;t.prototype=Object.create(n.prototype),s(t.prototype,i),s(t.prototype,a),s(t.prototype,r),s(t.prototype,o),l(u,t,document.createDocumentFragment()),e.wrappers.DocumentFragment=t;var d=c(document.createComment(""));e.wrappers.Comment=d}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(u(e).ownerDocument.createDocumentFragment());n.call(this,t),c(t,this);var o=e.shadowRoot;f.set(this,o),this.treeScope_=new r(this,a(o||e)),h.set(this,e)}var n=e.wrappers.DocumentFragment,r=e.TreeScope,o=e.elementFromPoint,i=e.getInnerHTML,a=e.getTreeScope,s=e.mixin,c=e.rewrap,l=e.setInnerHTML,u=e.unsafeUnwrap,d=e.unwrap,p=e.wrap,h=new WeakMap,f=new WeakMap;t.prototype=Object.create(n.prototype),s(t.prototype,{constructor:t,get innerHTML(){return i(this)},set innerHTML(e){l(this,e),this.invalidateShadowRenderer()},get olderShadowRoot(){return f.get(this)||null},get host(){return h.get(this)||null},invalidateShadowRenderer:function(){return h.get(this).invalidateShadowRenderer()},elementFromPoint:function(e,t){return o(this,this.ownerDocument,e,t)},getSelection:function(){return document.getSelection()},get activeElement(){var e=d(this).ownerDocument.activeElement;if(!e||!e.nodeType)return null;for(var t=p(e);!this.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}}),e.wrappers.ShadowRoot=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(e).root;return t instanceof h?t.host:null}function n(t,n){if(t.shadowRoot){n=Math.min(t.childNodes.length-1,n);var r=t.childNodes[n];if(r){var o=e.getDestinationInsertionPoints(r);if(o.length>0){var i=o[0].parentNode;i.nodeType==Node.ELEMENT_NODE&&(t=i)}}}return t}function r(e){return e=u(e),t(e)||e}function o(e){a(e,this)}var i=e.registerWrapper,a=e.setWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.unwrapIfNeeded,u=e.wrap,d=e.getTreeScope,p=window.Range,h=e.wrappers.ShadowRoot;o.prototype={get startContainer(){return r(s(this).startContainer)},get endContainer(){return r(s(this).endContainer)},get commonAncestorContainer(){return r(s(this).commonAncestorContainer)},setStart:function(e,t){e=n(e,t),s(this).setStart(l(e),t)},setEnd:function(e,t){e=n(e,t),s(this).setEnd(l(e),t)},setStartBefore:function(e){s(this).setStartBefore(l(e))},setStartAfter:function(e){s(this).setStartAfter(l(e))},setEndBefore:function(e){s(this).setEndBefore(l(e))},setEndAfter:function(e){s(this).setEndAfter(l(e))},selectNode:function(e){s(this).selectNode(l(e))},selectNodeContents:function(e){s(this).selectNodeContents(l(e))},compareBoundaryPoints:function(e,t){return s(this).compareBoundaryPoints(e,c(t))},extractContents:function(){return u(s(this).extractContents())},cloneContents:function(){return u(s(this).cloneContents())},insertNode:function(e){s(this).insertNode(l(e))},surroundContents:function(e){s(this).surroundContents(l(e))},cloneRange:function(){return u(s(this).cloneRange())},isPointInRange:function(e,t){return s(this).isPointInRange(l(e),t)},comparePoint:function(e,t){return s(this).comparePoint(l(e),t)},intersectsNode:function(e){return s(this).intersectsNode(l(e))},toString:function(){return s(this).toString()}},p.prototype.createContextualFragment&&(o.prototype.createContextualFragment=function(e){return u(s(this).createContextualFragment(e))}),i(window.Range,o,document.createRange()),e.wrappers.Range=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.previousSibling_=e.previousSibling,e.nextSibling_=e.nextSibling,e.parentNode_=e.parentNode}function n(n,o,i){var a=x(n),s=x(o),c=i?x(i):null;if(r(o),t(o),i)n.firstChild===i&&(n.firstChild_=i),i.previousSibling_=i.previousSibling;else{n.lastChild_=n.lastChild,n.lastChild===n.firstChild&&(n.firstChild_=n.firstChild);var l=R(a.lastChild);l&&(l.nextSibling_=l.nextSibling)}e.originalInsertBefore.call(a,s,c)}function r(n){var r=x(n),o=r.parentNode;if(o){var i=R(o);t(n),n.previousSibling&&(n.previousSibling.nextSibling_=n),n.nextSibling&&(n.nextSibling.previousSibling_=n),i.lastChild===n&&(i.lastChild_=n),i.firstChild===n&&(i.firstChild_=n),e.originalRemoveChild.call(o,r)}}function o(e){P.set(e,[])}function i(e){var t=P.get(e);return t||P.set(e,t=[]),t}function a(e){for(var t=[],n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t}function s(){for(var e=0;e=0;o--){var i=r[o],a=m(i);if(a){var s=i.olderShadowRoot;s&&(n=f(s));for(var c=0;c=0;u--)l=Object.create(l);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(e){var t=o[e];t&&(l[e]=function(){j(this)instanceof r||O(this),t.apply(j(this),arguments)})});var d={prototype:l};i&&(d["extends"]=i),r.prototype=o,r.prototype.constructor=r,e.constructorTable.set(l,r),e.nativePrototypeTable.set(o,l);k.call(C(this),t,d);return r},E([window.HTMLDocument||window.Document],["registerElement"])}E([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"]),E([window.HTMLBodyElement,window.HTMLHeadElement,window.HTMLHtmlElement],_),E([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","createTreeWalker","elementFromPoint","getElementById","getElementsByName","getSelection"]),S(t.prototype,l),S(t.prototype,d),S(t.prototype,f),S(t.prototype,p),S(t.prototype,{get implementation(){var e=H.get(this);return e?e:(e=new a(C(this).implementation),H.set(this,e),e)},get defaultView(){return j(C(this).defaultView)}}),T(window.Document,t,document.implementation.createHTMLDocument("")),window.HTMLDocument&&T(window.HTMLDocument,t),D([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]);var A=document.implementation.createDocument;a.prototype.createDocument=function(){return arguments[2]=C(arguments[2]),j(A.apply(N(this),arguments))},s(a,"createDocumentType"),s(a,"createHTMLDocument"),c(a,"hasFeature"),T(window.DOMImplementation,a),E([window.DOMImplementation],["createDocument","createDocumentType","createHTMLDocument","hasFeature"]),e.adoptNodeNoRemove=r,e.wrappers.DOMImplementation=a,e.wrappers.Document=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.wrappers.Selection,o=e.mixin,i=e.registerWrapper,a=e.renderAllPending,s=e.unwrap,c=e.unwrapIfNeeded,l=e.wrap,u=window.Window,d=window.getComputedStyle,p=window.getDefaultComputedStyle,h=window.getSelection;t.prototype=Object.create(n.prototype),u.prototype.getComputedStyle=function(e,t){return l(this||window).getComputedStyle(c(e),t)},p&&(u.prototype.getDefaultComputedStyle=function(e,t){return l(this||window).getDefaultComputedStyle(c(e),t)}),u.prototype.getSelection=function(){return l(this||window).getSelection()},delete window.getComputedStyle,delete window.getDefaultComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(e){u.prototype[e]=function(){var t=l(this||window);return t[e].apply(t,arguments)},delete window[e]}),o(t.prototype,{getComputedStyle:function(e,t){return a(),d.call(s(this),c(e),t)},getSelection:function(){return a(),new r(h.call(s(this)))},get document(){return l(s(this).document)}}),p&&(t.prototype.getDefaultComputedStyle=function(e,t){return a(),p.call(s(this),c(e),t)}),i(u,t,window),e.wrappers.Window=t}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrap,n=window.DataTransfer||window.Clipboard,r=n.prototype.setDragImage;r&&(n.prototype.setDragImage=function(e,n,o){r.call(this,t(e),n,o)})}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t;t=e instanceof i?e:new i(e&&o(e)),r(t,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unwrap,i=window.FormData;i&&(n(i,t,new i),e.wrappers.FormData=t)}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrapIfNeeded,n=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.send=function(e){return n.call(this,t(e))}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=n[e],r=window[t];if(r){var o=document.createElement(e),i=o.constructor;window[t]=i}}var n=(e.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(n).forEach(t),Object.getOwnPropertyNames(e.wrappers).forEach(function(t){window[t]=e.wrappers[t]})}(window.ShadowDOMPolyfill),function(e){function t(e,t){var n="";return Array.prototype.forEach.call(e,function(e){n+=e.textContent+"\n\n"}),t||(n=n.replace(d,"")),n}function n(e){var t=document.createElement("style");return t.textContent=e,t}function r(e){var t=n(e);document.head.appendChild(t);var r=[];if(t.sheet)try{r=t.sheet.cssRules}catch(o){}else console.warn("sheet not found",t);return t.parentNode.removeChild(t),r}function o(){C.initialized=!0,document.body.appendChild(C);var e=C.contentDocument,t=e.createElement("base");t.href=document.baseURI,e.head.appendChild(t)}function i(e){C.initialized||o(),document.body.appendChild(C),e(C.contentDocument),document.body.removeChild(C)}function a(e,t){if(t){var o;if(e.match("@import")&&D){var a=n(e);i(function(e){e.head.appendChild(a.impl),o=Array.prototype.slice.call(a.sheet.cssRules,0),t(o)})}else o=r(e),t(o)}}function s(e){e&&l().appendChild(document.createTextNode(e))}function c(e,t){var r=n(e);r.setAttribute(t,""),r.setAttribute(x,""),document.head.appendChild(r)}function l(){return j||(j=document.createElement("style"),j.setAttribute(x,""),j[x]=!0),j}var u={strictStyling:!1,registry:{},shimStyling:function(e,n,r){var o=this.prepareRoot(e,n,r),i=this.isTypeExtension(r),a=this.makeScopeSelector(n,i),s=t(o,!0);s=this.scopeCssText(s,a),e&&(e.shimmedStyle=s),this.addCssToDocument(s,n)},shimStyle:function(e,t){return this.shimCssText(e.textContent,t)},shimCssText:function(e,t){return e=this.insertDirectives(e),this.scopeCssText(e,t)},makeScopeSelector:function(e,t){return e?t?"[is="+e+"]":e:""},isTypeExtension:function(e){return e&&e.indexOf("-")<0},prepareRoot:function(e,t,n){var r=this.registerRoot(e,t,n);return this.replaceTextInStyles(r.rootStyles,this.insertDirectives),this.removeStyles(e,r.rootStyles),this.strictStyling&&this.applyScopeToContent(e,t),r.scopeStyles},removeStyles:function(e,t){for(var n,r=0,o=t.length;r","+","~"],r=e,o="["+t+"]";return n.forEach(function(e){var t=r.split(e);r=t.map(function(e){var t=e.trim().replace(L,"");return t&&n.indexOf(t)<0&&t.indexOf(o)<0&&(e=t.replace(/([^:]*)(:*)(.*)/,"$1"+o+"$2$3")),e}).join(e)}),r},insertPolyfillHostInCssText:function(e){return e.replace(M,b).replace(T,g)},propertiesFromRule:function(e){var t=e.style.cssText;e.style.content&&!e.style.content.match(/['"]+|attr/)&&(t=t.replace(/content:[^;]*;/g,"content: '"+e.style.content+"';"));var n=e.style;for(var r in n)"initial"===n[r]&&(t+=r+": initial; ");return t},replaceTextInStyles:function(e,t){e&&t&&(e instanceof Array||(e=[e]),Array.prototype.forEach.call(e,function(e){e.textContent=t.call(this,e.textContent)},this))},addCssToDocument:function(e,t){e.match("@import")?c(e,t):s(e)}},d=/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,p=/\/\*\s*@polyfill ([^*]*\*+([^\/*][^*]*\*+)*\/)([^{]*?){/gim,h=/polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim,f=/\/\*\s@polyfill-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,m=/(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,w=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,v=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,g="-shadowcsshost",b="-shadowcsscontext",y=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)",E=new RegExp("("+g+y,"gim"),_=new RegExp("("+b+y,"gim"),S="([>\\s~+[.,{:][\\s\\S]*)?$",T=/\:host/gim,M=/\:host-context/gim,O=g+"-no-combinator",L=new RegExp(g,"gim"),N=(new RegExp(b,"gim"),[/>>>/g,/::shadow/g,/::content/g,/\/deep\//g,/\/shadow\//g,/\/shadow-deep\//g,/\^\^/g,/\^(?!=)/g]),C=document.createElement("iframe");C.style.display="none";var j,D=navigator.userAgent.match("Chrome"),H="shim-shadowdom",x="shim-shadowdom-css",R="no-shim";if(window.ShadowDOMPolyfill){s("style { display: none !important; }\n");var I=ShadowDOMPolyfill.wrap(document),P=I.querySelector("head");P.insertBefore(l(),P.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){e.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var t="link[rel=stylesheet]["+H+"]",n="style["+H+"]";HTMLImports.importer.documentPreloadSelectors+=","+t,HTMLImports.importer.importsPreloadSelectors+=","+t,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,t,n].join(",");var r=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(e){if(!e[x]){var t=e.__importElement||e;if(!t.hasAttribute(H))return void r.call(this,e);e.__resource&&(t=e.ownerDocument.createElement("style"),t.textContent=e.__resource),HTMLImports.path.resolveUrlsInStyle(t,e.href),t.textContent=u.shimStyle(t),t.removeAttribute(H,""),t.setAttribute(x,""),t[x]=!0,t.parentNode!==P&&(e.parentNode===P?P.replaceChild(t,e):this.addElementToDocument(t)),t.__importParsed=!0,this.markParsingComplete(e),this.parseNext()}};var o=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(e){return"link"===e.localName&&"stylesheet"===e.rel&&e.hasAttribute(H)?e.__resource:o.call(this,e)}}})}e.ShadowCSS=u}(window.WebComponents)),function(e){window.ShadowDOMPolyfill?(window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}}(window.WebComponents),function(e){"use strict";function t(e){return void 0!==p[e]}function n(){s.call(this),this._isInvalid=!0}function r(e){return""==e&&n.call(this),e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,63,96].indexOf(t)==-1?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,96].indexOf(t)==-1?e:encodeURIComponent(e)}function a(e,a,s){function c(e){b.push(e)}var l=a||"scheme start",u=0,d="",v=!1,g=!1,b=[];e:for(;(e[u-1]!=f||0==u)&&!this._isInvalid;){var y=e[u];switch(l){case"scheme start":if(!y||!m.test(y)){if(a){c("Invalid scheme.");break e}d="",l="no scheme";continue}d+=y.toLowerCase(),l="scheme";break;case"scheme":if(y&&w.test(y))d+=y.toLowerCase();else{if(":"!=y){if(a){if(f==y)break e;c("Code point not allowed in scheme: "+y);break e}d="",u=0,l="no scheme";continue}if(this._scheme=d,d="",a)break e;t(this._scheme)&&(this._isRelative=!0),l="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==y?(this._query="?",l="query"):"#"==y?(this._fragment="#",l="fragment"):f!=y&&"\t"!=y&&"\n"!=y&&"\r"!=y&&(this._schemeData+=o(y));break;case"no scheme":if(s&&t(s._scheme)){l="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=y||"/"!=e[u+1]){c("Expected /, got: "+y),l="relative";continue}l="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),f==y){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==y||"\\"==y)"\\"==y&&c("\\ is an invalid code point."),l="relative slash";else if("?"==y)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,l="query";else{if("#"!=y){var E=e[u+1],_=e[u+2];("file"!=this._scheme||!m.test(y)||":"!=E&&"|"!=E||f!=_&&"/"!=_&&"\\"!=_&&"?"!=_&&"#"!=_)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),l="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,l="fragment"}break;case"relative slash":if("/"!=y&&"\\"!=y){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),l="relative path";continue}"\\"==y&&c("\\ is an invalid code point."),l="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=y){c("Expected '/', got: "+y),l="authority ignore slashes";continue}l="authority second slash";break;case"authority second slash":if(l="authority ignore slashes","/"!=y){c("Expected '/', got: "+y);continue}break;case"authority ignore slashes":if("/"!=y&&"\\"!=y){l="authority";continue}c("Expected authority, got: "+y);break;case"authority":if("@"==y){v&&(c("@ already seen."),d+="%40"),v=!0;for(var S=0;S0){var o=n[r-1],i=h(o,e);if(i)return void(n[r-1]=i)}else t(this.observer);n[r]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=w.get(e);t||w.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=w.get(e),n=0;n=200&&e.status<300||304===e.status||0===e.status},load:function(n,r,o){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}r.call(o,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,r=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};r.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,r=e.length;n-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,r,null,a)}.bind(this),0)}else{var s=function(t,n,o){this.receive(e,r,t,n,o)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,r,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,r,o){this.cache[e]=r;for(var i,a=this.pending[e],s=0,c=a.length;s=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,r=function(o){e.removeEventListener("load",r),e.removeEventListener("error",r),t&&t(o),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",r),e.addEventListener("error",r),l&&"style"===e.localName){var o=!1;if(e.textContent.indexOf("@import")==-1)o=!0;else if(e.sheet){o=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;c=0},hasResource:function(e){return!t(e)||void 0!==e.__doc}};e.parser=p,e.IMPORT_SELECTOR=d}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function r(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function o(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var o=n.createElement("base");o.setAttribute("href",t),n.baseURI||r(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(o),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,l=e.Loader,u=e.Observer,d=e.parser,p={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){h.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);h.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,r,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=r,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:o(r,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}d.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),d.parseNext()},loadedAll:function(){d.parseNext()}},h=new l(p.loaded.bind(p),p.loadedAll.bind(p));if(p.observer=new u,!document.baseURI){var f={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",f),Object.defineProperty(c,"baseURI",f)}e.importer=p,e.importLoader=h}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,r={added:function(e){for(var r,o,i,a,s=0,c=e.length;s=0)){n.push(e);for(var r,o=e.querySelectorAll("link[rel="+a+"]"),s=0,c=o.length;s=0&&b(r,HTMLElement),r)}function f(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return v(e),e}}var m,w=(e.isIE,e.upgradeDocumentTree),v=e.upgradeAll,g=e.upgradeWithDefinition,b=e.implementPrototype,y=e.useNative,E=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],_={},S="http://www.w3.org/1999/xhtml",T=document.createElement.bind(document),M=document.createElementNS.bind(document);m=Object.__proto__||y?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},f(Node.prototype,"cloneNode"),f(document,"importNode"),document.registerElement=t,document.createElement=h,document.createElementNS=p,e.registry=_,e["instanceof"]=m,e.reservedTagList=E,e.getRegisteredDefinition=l,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,r=e.initializeModules;e.isIE;if(n){var o=function(){};e.watchShadow=o,e.upgrade=o,e.upgradeAll=o,e.upgradeDocumentTree=o,e.upgradeSubtree=o,e.takeRecords=o,e["instanceof"]=function(e,t){return e instanceof t}}else r();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){Function.prototype.bind||(Function.prototype.bind=function(e){var t=this,n=Array.prototype.slice.call(arguments,1);return function(){var r=n.slice();return r.push.apply(r,arguments),t.apply(e,r)}})}(window.WebComponents),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents),function(e){window.Platform=e}(window.WebComponents); \ No newline at end of file diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go index 0139639dae..a0d742ac54 100644 --- a/src/cmd/trace/trace.go +++ b/src/cmd/trace/trace.go @@ -6,6 +6,7 @@ package main import ( "cmd/internal/traceviewer" + "embed" "encoding/json" "fmt" "internal/trace" @@ -13,8 +14,6 @@ import ( "log" "math" "net/http" - "path/filepath" - "runtime" "runtime/debug" "sort" "strconv" @@ -22,13 +21,16 @@ import ( "time" ) +//go:embed static/trace_viewer_full.html static/webcomponents.min.js +var staticContent embed.FS + func init() { http.HandleFunc("/trace", httpTrace) http.HandleFunc("/jsontrace", httpJsonTrace) - http.HandleFunc("/trace_viewer_html", httpTraceViewerHTML) - http.HandleFunc("/webcomponents.min.js", webcomponentsJS) + http.Handle("/static/", http.FileServer(http.FS(staticContent))) } + // httpTrace serves either whole trace (goid==0) or trace for goid goroutine. func httpTrace(w http.ResponseWriter, r *http.Request) { _, err := parseTrace() @@ -50,19 +52,19 @@ func httpTrace(w http.ResponseWriter, r *http.Request) { var templTrace = ` - + -