summaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-10-28 09:12:20 -0400
committerCherry Zhang <cherryyz@google.com>2020-10-28 09:12:20 -0400
commita16e30d162c1c7408db7821e7b9513cefa09c6ca (patch)
treeaf752ba9ba44c547df39bb0af9bff79f610ba9d5 /src/internal
parent91e4d2d57bc341dd82c98247117114c851380aef (diff)
parentcf6cfba4d5358404dd890f6025e573a4b2156543 (diff)
downloadgo-git-dev.link.tar.gz
[dev.link] all: merge branch 'master' into dev.linkdev.link
Clean merge. Change-Id: Ia7b2808bc649790198d34c226a61d9e569084dc5
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/bytealg/bytealg.go4
-rw-r--r--src/internal/bytealg/count_generic.go2
-rw-r--r--src/internal/bytealg/count_native.go2
-rw-r--r--src/internal/bytealg/count_riscv64.s44
-rw-r--r--src/internal/bytealg/equal_mips64x.s72
-rw-r--r--src/internal/cpu/cpu_android.go7
-rw-r--r--src/internal/cpu/cpu_arm64.go141
-rw-r--r--src/internal/cpu/cpu_arm64.s12
-rw-r--r--src/internal/cpu/cpu_freebsd.go7
-rw-r--r--src/internal/cpu/cpu_linux.go9
-rw-r--r--src/internal/cpu/cpu_mips.go3
-rw-r--r--src/internal/cpu/cpu_mipsle.go3
-rw-r--r--src/internal/cpu/cpu_no_init.go18
-rw-r--r--src/internal/cpu/cpu_no_name.go19
-rw-r--r--src/internal/cpu/cpu_other.go11
-rw-r--r--src/internal/cpu/cpu_riscv64.go3
-rw-r--r--src/internal/cpu/cpu_s390x.go15
-rw-r--r--src/internal/cpu/cpu_test.go9
-rw-r--r--src/internal/cpu/cpu_wasm.go3
-rw-r--r--src/internal/cpu/cpu_x86.go49
-rw-r--r--src/internal/obscuretestdata/obscuretestdata.go2
-rw-r--r--src/internal/poll/error_test.go3
-rw-r--r--src/internal/poll/fd_fsync_darwin.go7
-rw-r--r--src/internal/poll/fd_unix.go7
-rw-r--r--src/internal/poll/hook_cloexec.go2
-rw-r--r--src/internal/poll/sock_cloexec.go2
-rw-r--r--src/internal/poll/sys_cloexec.go2
-rw-r--r--src/internal/profile/profile.go5
-rw-r--r--src/internal/reflectlite/reflect_mirror_test.go3
-rw-r--r--src/internal/reflectlite/type.go73
-rw-r--r--src/internal/reflectlite/value.go9
-rw-r--r--src/internal/syscall/windows/registry/key.go17
-rw-r--r--src/internal/syscall/windows/registry/registry_test.go6
-rw-r--r--src/internal/syscall/windows/registry/value.go13
-rw-r--r--src/internal/sysinfo/sysinfo.go31
-rw-r--r--src/internal/testenv/testenv.go44
36 files changed, 487 insertions, 172 deletions
diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go
index 6fd9308369..b30c234436 100644
--- a/src/internal/bytealg/bytealg.go
+++ b/src/internal/bytealg/bytealg.go
@@ -99,7 +99,7 @@ func HashStrRev(sep string) (uint32, uint32) {
}
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
-// first occurence of substr in s, or -1 if not present.
+// first occurrence of substr in s, or -1 if not present.
func IndexRabinKarpBytes(s, sep []byte) int {
// Rabin-Karp search
hashsep, pow := HashStrBytes(sep)
@@ -124,7 +124,7 @@ func IndexRabinKarpBytes(s, sep []byte) int {
}
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
-// first occurence of substr in s, or -1 if not present.
+// first occurrence of substr in s, or -1 if not present.
func IndexRabinKarp(s, substr string) int {
// Rabin-Karp search
hashss, pow := HashStr(substr)
diff --git a/src/internal/bytealg/count_generic.go b/src/internal/bytealg/count_generic.go
index 7cc1d50312..5575e81ab8 100644
--- a/src/internal/bytealg/count_generic.go
+++ b/src/internal/bytealg/count_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!arm,!arm64,!ppc64le,!ppc64,!s390x
+// +build !amd64,!arm,!arm64,!ppc64le,!ppc64,!riscv64,!s390x
package bytealg
diff --git a/src/internal/bytealg/count_native.go b/src/internal/bytealg/count_native.go
index 0448fca9e8..b1ff1d265a 100644
--- a/src/internal/bytealg/count_native.go
+++ b/src/internal/bytealg/count_native.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 arm arm64 ppc64le ppc64 s390x
+// +build amd64 arm arm64 ppc64le ppc64 riscv64 s390x
package bytealg
diff --git a/src/internal/bytealg/count_riscv64.s b/src/internal/bytealg/count_riscv64.s
new file mode 100644
index 0000000000..3f4eb23286
--- /dev/null
+++ b/src/internal/bytealg/count_riscv64.s
@@ -0,0 +1,44 @@
+// Copyright 2020 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.
+
+#include "go_asm.h"
+#include "textflag.h"
+
+TEXT ·Count(SB),NOSPLIT,$0-40
+ MOV b_base+0(FP), A1
+ MOV b_len+8(FP), A2
+ MOVBU c+24(FP), A3 // byte to count
+ MOV ZERO, A4 // count
+ ADD A1, A2 // end
+
+loop:
+ BEQ A1, A2, done
+ MOVBU (A1), A5
+ ADD $1, A1
+ BNE A3, A5, loop
+ ADD $1, A4
+ JMP loop
+
+done:
+ MOV A4, ret+32(FP)
+ RET
+
+TEXT ·CountString(SB),NOSPLIT,$0-32
+ MOV s_base+0(FP), A1
+ MOV s_len+8(FP), A2
+ MOVBU c+16(FP), A3 // byte to count
+ MOV ZERO, A4 // count
+ ADD A1, A2 // end
+
+loop:
+ BEQ A1, A2, done
+ MOVBU (A1), A5
+ ADD $1, A1
+ BNE A3, A5, loop
+ ADD $1, A4
+ JMP loop
+
+done:
+ MOV A4, ret+24(FP)
+ RET
diff --git a/src/internal/bytealg/equal_mips64x.s b/src/internal/bytealg/equal_mips64x.s
index 58dc4303b4..641e3ff06c 100644
--- a/src/internal/bytealg/equal_mips64x.s
+++ b/src/internal/bytealg/equal_mips64x.s
@@ -16,18 +16,82 @@ TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
BEQ R1, R2, eq
MOVV size+16(FP), R3
ADDV R1, R3, R4
-loop:
- BNE R1, R4, test
+
+ // chunk size is 16
+ SGTU $16, R3, R8
+ BEQ R0, R8, chunk_entry
+
+byte_loop:
+ BNE R1, R4, byte_test
MOVV $1, R1
MOVB R1, ret+24(FP)
RET
-test:
+byte_test:
MOVBU (R1), R6
ADDV $1, R1
MOVBU (R2), R7
ADDV $1, R2
- BEQ R6, R7, loop
+ BEQ R6, R7, byte_loop
+ JMP not_eq
+
+chunk_entry:
+ // make sure both a and b are aligned
+ OR R1, R2, R9
+ AND $0x7, R9
+ BNE R0, R9, byte_loop
+ JMP chunk_loop_1
+
+chunk_loop:
+ // chunk size is 16
+ SGTU $16, R3, R8
+ BNE R0, R8, chunk_tail_8
+chunk_loop_1:
+ MOVV (R1), R6
+ MOVV (R2), R7
+ BNE R6, R7, not_eq
+ MOVV 8(R1), R12
+ MOVV 8(R2), R13
+ ADDV $16, R1
+ ADDV $16, R2
+ SUBV $16, R3
+ BEQ R12, R13, chunk_loop
+ JMP not_eq
+
+chunk_tail_8:
+ AND $8, R3, R14
+ BEQ R0, R14, chunk_tail_4
+ MOVV (R1), R6
+ MOVV (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $8, R1
+ ADDV $8, R2
+
+chunk_tail_4:
+ AND $4, R3, R14
+ BEQ R0, R14, chunk_tail_2
+ MOVWU (R1), R6
+ MOVWU (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $4, R1
+ ADDV $4, R2
+
+chunk_tail_2:
+ AND $2, R3, R14
+ BEQ R0, R14, chunk_tail_1
+ MOVHU (R1), R6
+ MOVHU (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $2, R1
+ ADDV $2, R2
+
+chunk_tail_1:
+ AND $1, R3, R14
+ BEQ R0, R14, eq
+ MOVBU (R1), R6
+ MOVBU (R2), R7
+ BEQ R6, R7, eq
+not_eq:
MOVB R0, ret+24(FP)
RET
eq:
diff --git a/src/internal/cpu/cpu_android.go b/src/internal/cpu/cpu_android.go
new file mode 100644
index 0000000000..d995e8d5a7
--- /dev/null
+++ b/src/internal/cpu/cpu_android.go
@@ -0,0 +1,7 @@
+// Copyright 2020 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 cpu
+
+const GOOS = "android"
diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go
index efdb3b9e33..533bea2470 100644
--- a/src/internal/cpu/cpu_arm64.go
+++ b/src/internal/cpu/cpu_arm64.go
@@ -6,97 +6,90 @@ package cpu
const CacheLinePadSize = 64
-// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
-// These are initialized by archauxv and should not be changed after they are
-// initialized.
+// HWCap may be initialized by archauxv and
+// should not be changed after it was initialized.
var HWCap uint
-var HWCap2 uint
-// HWCAP/HWCAP2 bits. These are exposed by Linux.
+// HWCAP bits. These are exposed by Linux.
const (
- hwcap_FP = 1 << 0
- hwcap_ASIMD = 1 << 1
- hwcap_EVTSTRM = 1 << 2
- hwcap_AES = 1 << 3
- hwcap_PMULL = 1 << 4
- hwcap_SHA1 = 1 << 5
- hwcap_SHA2 = 1 << 6
- hwcap_CRC32 = 1 << 7
- hwcap_ATOMICS = 1 << 8
- hwcap_FPHP = 1 << 9
- hwcap_ASIMDHP = 1 << 10
- hwcap_CPUID = 1 << 11
- hwcap_ASIMDRDM = 1 << 12
- hwcap_JSCVT = 1 << 13
- hwcap_FCMA = 1 << 14
- hwcap_LRCPC = 1 << 15
- hwcap_DCPOP = 1 << 16
- hwcap_SHA3 = 1 << 17
- hwcap_SM3 = 1 << 18
- hwcap_SM4 = 1 << 19
- hwcap_ASIMDDP = 1 << 20
- hwcap_SHA512 = 1 << 21
- hwcap_SVE = 1 << 22
- hwcap_ASIMDFHM = 1 << 23
+ hwcap_AES = 1 << 3
+ hwcap_PMULL = 1 << 4
+ hwcap_SHA1 = 1 << 5
+ hwcap_SHA2 = 1 << 6
+ hwcap_CRC32 = 1 << 7
+ hwcap_ATOMICS = 1 << 8
)
func doinit() {
options = []option{
- {Name: "evtstrm", Feature: &ARM64.HasEVTSTRM},
{Name: "aes", Feature: &ARM64.HasAES},
{Name: "pmull", Feature: &ARM64.HasPMULL},
{Name: "sha1", Feature: &ARM64.HasSHA1},
{Name: "sha2", Feature: &ARM64.HasSHA2},
{Name: "crc32", Feature: &ARM64.HasCRC32},
{Name: "atomics", Feature: &ARM64.HasATOMICS},
- {Name: "fphp", Feature: &ARM64.HasFPHP},
- {Name: "asimdhp", Feature: &ARM64.HasASIMDHP},
- {Name: "cpuid", Feature: &ARM64.HasCPUID},
- {Name: "asimdrdm", Feature: &ARM64.HasASIMDRDM},
- {Name: "jscvt", Feature: &ARM64.HasJSCVT},
- {Name: "fcma", Feature: &ARM64.HasFCMA},
- {Name: "lrcpc", Feature: &ARM64.HasLRCPC},
- {Name: "dcpop", Feature: &ARM64.HasDCPOP},
- {Name: "sha3", Feature: &ARM64.HasSHA3},
- {Name: "sm3", Feature: &ARM64.HasSM3},
- {Name: "sm4", Feature: &ARM64.HasSM4},
- {Name: "asimddp", Feature: &ARM64.HasASIMDDP},
- {Name: "sha512", Feature: &ARM64.HasSHA512},
- {Name: "sve", Feature: &ARM64.HasSVE},
- {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM},
-
- // These capabilities should always be enabled on arm64:
- {Name: "fp", Feature: &ARM64.HasFP, Required: true},
- {Name: "asimd", Feature: &ARM64.HasASIMD, Required: true},
}
- // HWCAP feature bits
- ARM64.HasFP = isSet(HWCap, hwcap_FP)
- ARM64.HasASIMD = isSet(HWCap, hwcap_ASIMD)
- ARM64.HasEVTSTRM = isSet(HWCap, hwcap_EVTSTRM)
- ARM64.HasAES = isSet(HWCap, hwcap_AES)
- ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
- ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
- ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
- ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
- ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS)
- ARM64.HasFPHP = isSet(HWCap, hwcap_FPHP)
- ARM64.HasASIMDHP = isSet(HWCap, hwcap_ASIMDHP)
- ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
- ARM64.HasASIMDRDM = isSet(HWCap, hwcap_ASIMDRDM)
- ARM64.HasJSCVT = isSet(HWCap, hwcap_JSCVT)
- ARM64.HasFCMA = isSet(HWCap, hwcap_FCMA)
- ARM64.HasLRCPC = isSet(HWCap, hwcap_LRCPC)
- ARM64.HasDCPOP = isSet(HWCap, hwcap_DCPOP)
- ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3)
- ARM64.HasSM3 = isSet(HWCap, hwcap_SM3)
- ARM64.HasSM4 = isSet(HWCap, hwcap_SM4)
- ARM64.HasASIMDDP = isSet(HWCap, hwcap_ASIMDDP)
- ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512)
- ARM64.HasSVE = isSet(HWCap, hwcap_SVE)
- ARM64.HasASIMDFHM = isSet(HWCap, hwcap_ASIMDFHM)
+ switch GOOS {
+ case "linux", "android":
+ // HWCap was populated by the runtime from the auxillary vector.
+ // Use HWCap information since reading aarch64 system registers
+ // is not supported in user space on older linux kernels.
+ ARM64.HasAES = isSet(HWCap, hwcap_AES)
+ ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
+ ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
+ ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
+ ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
+
+ // The Samsung S9+ kernel reports support for atomics, but not all cores
+ // actually support them, resulting in SIGILL. See issue #28431.
+ // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
+ ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android"
+
+ case "freebsd":
+ // Retrieve info from system register ID_AA64ISAR0_EL1.
+ isar0 := getisar0()
+
+ // ID_AA64ISAR0_EL1
+ switch extractBits(isar0, 4, 7) {
+ case 1:
+ ARM64.HasAES = true
+ case 2:
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ }
+
+ switch extractBits(isar0, 8, 11) {
+ case 1:
+ ARM64.HasSHA1 = true
+ }
+
+ switch extractBits(isar0, 12, 15) {
+ case 1, 2:
+ ARM64.HasSHA2 = true
+ }
+
+ switch extractBits(isar0, 16, 19) {
+ case 1:
+ ARM64.HasCRC32 = true
+ }
+
+ switch extractBits(isar0, 20, 23) {
+ case 2:
+ ARM64.HasATOMICS = true
+ }
+ default:
+ // Other operating systems do not support reading HWCap from auxillary vector
+ // or reading privileged aarch64 system registers in user space.
+ }
+}
+
+func extractBits(data uint64, start, end uint) uint {
+ return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
}
func isSet(hwc uint, value uint) bool {
return hwc&value != 0
}
+
+func getisar0() uint64
diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s
new file mode 100644
index 0000000000..d85914973f
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64.s
@@ -0,0 +1,12 @@
+// Copyright 2020 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.
+
+#include "textflag.h"
+
+// func getisar0() uint64
+TEXT ·getisar0(SB),NOSPLIT,$0
+ // get Instruction Set Attributes 0 into R0
+ MRS ID_AA64ISAR0_EL1, R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/src/internal/cpu/cpu_freebsd.go b/src/internal/cpu/cpu_freebsd.go
new file mode 100644
index 0000000000..dc37173dac
--- /dev/null
+++ b/src/internal/cpu/cpu_freebsd.go
@@ -0,0 +1,7 @@
+// Copyright 2020 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 cpu
+
+const GOOS = "freebsd"
diff --git a/src/internal/cpu/cpu_linux.go b/src/internal/cpu/cpu_linux.go
new file mode 100644
index 0000000000..ec0b84c510
--- /dev/null
+++ b/src/internal/cpu/cpu_linux.go
@@ -0,0 +1,9 @@
+// Copyright 2020 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.
+
+// +build !android
+
+package cpu
+
+const GOOS = "linux"
diff --git a/src/internal/cpu/cpu_mips.go b/src/internal/cpu/cpu_mips.go
index 0f821e44e7..14a9c975ea 100644
--- a/src/internal/cpu/cpu_mips.go
+++ b/src/internal/cpu/cpu_mips.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_mipsle.go b/src/internal/cpu/cpu_mipsle.go
index 0f821e44e7..14a9c975ea 100644
--- a/src/internal/cpu/cpu_mipsle.go
+++ b/src/internal/cpu/cpu_mipsle.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_no_init.go b/src/internal/cpu/cpu_no_init.go
deleted file mode 100644
index fb381e1ce2..0000000000
--- a/src/internal/cpu/cpu_no_init.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 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.
-
-// +build !386
-// +build !amd64
-// +build !arm
-// +build !arm64
-// +build !ppc64
-// +build !ppc64le
-// +build !s390x
-// +build !mips64
-// +build !mips64le
-
-package cpu
-
-func doinit() {
-}
diff --git a/src/internal/cpu/cpu_no_name.go b/src/internal/cpu/cpu_no_name.go
new file mode 100644
index 0000000000..ce1c37a3c7
--- /dev/null
+++ b/src/internal/cpu/cpu_no_name.go
@@ -0,0 +1,19 @@
+// Copyright 2020 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.
+
+// +build !386
+// +build !amd64
+
+package cpu
+
+// Name returns the CPU name given by the vendor
+// if it can be read directly from memory or by CPU instructions.
+// If the CPU name can not be determined an empty string is returned.
+//
+// Implementations that use the Operating System (e.g. sysctl or /sys/)
+// to gather CPU information for display should be placed in internal/sysinfo.
+func Name() string {
+ // "A CPU has no name".
+ return ""
+}
diff --git a/src/internal/cpu/cpu_other.go b/src/internal/cpu/cpu_other.go
new file mode 100644
index 0000000000..8a15fbe79d
--- /dev/null
+++ b/src/internal/cpu/cpu_other.go
@@ -0,0 +1,11 @@
+// Copyright 2020 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.
+
+// +build !linux
+// +build !freebsd
+// +build !android
+
+package cpu
+
+const GOOS = "other"
diff --git a/src/internal/cpu/cpu_riscv64.go b/src/internal/cpu/cpu_riscv64.go
index c49cab79fd..54b8c3378b 100644
--- a/src/internal/cpu/cpu_riscv64.go
+++ b/src/internal/cpu/cpu_riscv64.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_s390x.go b/src/internal/cpu/cpu_s390x.go
index 526e074225..45d8ed27f0 100644
--- a/src/internal/cpu/cpu_s390x.go
+++ b/src/internal/cpu/cpu_s390x.go
@@ -6,6 +6,8 @@ package cpu
const CacheLinePadSize = 256
+var HWCap uint
+
// bitIsSet reports whether the bit at index is set. The bit index
// is in big endian order, so bit index 0 is the leftmost bit.
func bitIsSet(bits []uint64, index uint) bool {
@@ -95,8 +97,10 @@ const (
// vector facilities
vxe facility = 135 // vector-enhancements 1
- // Note: vx and highgprs are excluded because they require
- // kernel support and so must be fetched from HWCAP.
+ // Note: vx requires kernel support
+ // and so must be fetched from HWCAP.
+
+ hwcap_VX = 1 << 11 // vector facility
)
// facilityList contains the result of an STFLE call.
@@ -188,7 +192,14 @@ func doinit() {
S390X.HasEDDSA = kdsa.Has(eddsaVerifyEd25519, eddsaSignEd25519, eddsaVerifyEd448, eddsaSignEd448)
}
}
+
+ S390X.HasVX = isSet(HWCap, hwcap_VX)
+
if S390X.HasVX {
S390X.HasVXE = facilities.Has(vxe)
}
}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go
index e09bd2d8b9..919bbd5ed7 100644
--- a/src/internal/cpu/cpu_test.go
+++ b/src/internal/cpu/cpu_test.go
@@ -15,6 +15,7 @@ import (
)
func TestMinimalFeatures(t *testing.T) {
+ // TODO: maybe do MustSupportFeatureDectection(t) ?
if runtime.GOARCH == "arm64" {
switch runtime.GOOS {
case "linux", "android":
@@ -36,6 +37,13 @@ func MustHaveDebugOptionsSupport(t *testing.T) {
}
}
+func MustSupportFeatureDectection(t *testing.T) {
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
+ t.Skipf("CPU feature detection is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+ // TODO: maybe there are other platforms?
+}
+
func runDebugOptionsTest(t *testing.T, test string, options string) {
MustHaveDebugOptionsSupport(t)
@@ -58,6 +66,7 @@ func runDebugOptionsTest(t *testing.T, test string, options string) {
}
func TestDisableAllCapabilities(t *testing.T) {
+ MustSupportFeatureDectection(t)
runDebugOptionsTest(t, "TestAllCapabilitiesDisabled", "cpu.all=off")
}
diff --git a/src/internal/cpu/cpu_wasm.go b/src/internal/cpu/cpu_wasm.go
index b459738770..2310ad6a48 100644
--- a/src/internal/cpu/cpu_wasm.go
+++ b/src/internal/cpu/cpu_wasm.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 64
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go
index da6cf67258..fb414adaf8 100644
--- a/src/internal/cpu/cpu_x86.go
+++ b/src/internal/cpu/cpu_x86.go
@@ -38,6 +38,8 @@ const (
cpuid_ADX = 1 << 19
)
+var maxExtendedFunctionInformation uint32
+
func doinit() {
options = []option{
{Name: "adx", Feature: &X86.HasADX},
@@ -65,6 +67,8 @@ func doinit() {
return
}
+ maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
+
_, _, ecx1, edx1 := cpuid(1, 0)
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
@@ -103,3 +107,48 @@ func doinit() {
func isSet(hwc uint32, value uint32) bool {
return hwc&value != 0
}
+
+// Name returns the CPU name given by the vendor.
+// If the CPU name can not be determined an
+// empty string is returned.
+func Name() string {
+ if maxExtendedFunctionInformation < 0x80000004 {
+ return ""
+ }
+
+ data := make([]byte, 0, 3*4*4)
+
+ var eax, ebx, ecx, edx uint32
+ eax, ebx, ecx, edx = cpuid(0x80000002, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000003, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000004, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+
+ // Trim leading spaces.
+ for len(data) > 0 && data[0] == ' ' {
+ data = data[1:]
+ }
+
+ // Trim tail after and including the first null byte.
+ for i, c := range data {
+ if c == '\x00' {
+ data = data[:i]
+ break
+ }
+ }
+
+ return string(data)
+}
+
+func appendBytes(b []byte, args ...uint32) []byte {
+ for _, arg := range args {
+ b = append(b,
+ byte((arg >> 0)),
+ byte((arg >> 8)),
+ byte((arg >> 16)),
+ byte((arg >> 24)))
+ }
+ return b
+}
diff --git a/src/internal/obscuretestdata/obscuretestdata.go b/src/internal/obscuretestdata/obscuretestdata.go
index 512f3759b4..06cd1df22c 100644
--- a/src/internal/obscuretestdata/obscuretestdata.go
+++ b/src/internal/obscuretestdata/obscuretestdata.go
@@ -47,5 +47,5 @@ func ReadFile(name string) ([]byte, error) {
return nil, err
}
defer f.Close()
- return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
+ return io.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
}
diff --git a/src/internal/poll/error_test.go b/src/internal/poll/error_test.go
index 06b96f635a..abc8b1684f 100644
--- a/src/internal/poll/error_test.go
+++ b/src/internal/poll/error_test.go
@@ -6,6 +6,7 @@ package poll_test
import (
"fmt"
+ "io/fs"
"net"
"os"
"testing"
@@ -37,7 +38,7 @@ func parseReadError(nestedErr error, verify func(error) (string, bool)) error {
if nerr, ok := err.(*net.OpError); ok {
err = nerr.Err
}
- if nerr, ok := err.(*os.PathError); ok {
+ if nerr, ok := err.(*fs.PathError); ok {
err = nerr.Err
}
if nerr, ok := err.(*os.SyscallError); ok {
diff --git a/src/internal/poll/fd_fsync_darwin.go b/src/internal/poll/fd_fsync_darwin.go
index 91751496a4..48e7596922 100644
--- a/src/internal/poll/fd_fsync_darwin.go
+++ b/src/internal/poll/fd_fsync_darwin.go
@@ -14,7 +14,8 @@ func (fd *FD) Fsync() error {
return err
}
defer fd.decref()
-
- _, e1 := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
- return e1
+ return ignoringEINTR(func() error {
+ _, err := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
+ return err
+ })
}
diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go
index f6f6c52f31..2e77e76c87 100644
--- a/src/internal/poll/fd_unix.go
+++ b/src/internal/poll/fd_unix.go
@@ -74,7 +74,14 @@ func (fd *FD) destroy() error {
// Poller may want to unregister fd in readiness notification mechanism,
// so this must be executed before CloseFunc.
fd.pd.close()
+
+ // We don't use ignoringEINTR here because POSIX does not define
+ // whether the descriptor is closed if close returns EINTR.
+ // If the descriptor is indeed closed, using a loop would race
+ // with some other goroutine opening a new descriptor.
+ // (The Linux kernel guarantees that it is closed on an EINTR error.)
err := CloseFunc(fd.Sysfd)
+
fd.Sysfd = -1
runtime_Semrelease(&fd.csema)
return err
diff --git a/src/internal/poll/hook_cloexec.go b/src/internal/poll/hook_cloexec.go
index 5c93bdaf6c..5fd5449bb0 100644
--- a/src/internal/poll/hook_cloexec.go
+++ b/src/internal/poll/hook_cloexec.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build dragonfly freebsd linux netbsd openbsd
+// +build dragonfly freebsd illumos linux netbsd openbsd
package poll
diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go
index 691cb8e36f..ff7982ca9e 100644
--- a/src/internal/poll/sock_cloexec.go
+++ b/src/internal/poll/sock_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build dragonfly freebsd linux netbsd openbsd
+// +build dragonfly freebsd illumos linux netbsd openbsd
package poll
diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go
index 7b87f136df..4b3c642173 100644
--- a/src/internal/poll/sys_cloexec.go
+++ b/src/internal/poll/sys_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build aix darwin js,wasm solaris
+// +build aix darwin js,wasm solaris,!illumos
package poll
diff --git a/src/internal/profile/profile.go b/src/internal/profile/profile.go
index a6275bc6de..29568aa4b5 100644
--- a/src/internal/profile/profile.go
+++ b/src/internal/profile/profile.go
@@ -12,7 +12,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"regexp"
"strings"
"time"
@@ -125,7 +124,7 @@ type Function struct {
// may be a gzip-compressed encoded protobuf or one of many legacy
// profile formats which may be unsupported in the future.
func Parse(r io.Reader) (*Profile, error) {
- orig, err := ioutil.ReadAll(r)
+ orig, err := io.ReadAll(r)
if err != nil {
return nil, err
}
@@ -136,7 +135,7 @@ func Parse(r io.Reader) (*Profile, error) {
if err != nil {
return nil, fmt.Errorf("decompressing profile: %v", err)
}
- data, err := ioutil.ReadAll(gz)
+ data, err := io.ReadAll(gz)
if err != nil {
return nil, fmt.Errorf("decompressing profile: %v", err)
}
diff --git a/src/internal/reflectlite/reflect_mirror_test.go b/src/internal/reflectlite/reflect_mirror_test.go
index fbb6fb397e..9b28b13550 100644
--- a/src/internal/reflectlite/reflect_mirror_test.go
+++ b/src/internal/reflectlite/reflect_mirror_test.go
@@ -9,6 +9,7 @@ import (
"go/ast"
"go/parser"
"go/token"
+ "io/fs"
"os"
"path/filepath"
"runtime"
@@ -71,7 +72,7 @@ func (v visitor) Visit(n ast.Node) ast.Visitor {
func loadTypes(path, pkgName string, v visitor) {
fset := token.NewFileSet()
- filter := func(fi os.FileInfo) bool {
+ filter := func(fi fs.FileInfo) bool {
return strings.HasSuffix(fi.Name(), ".go")
}
pkgs, err := parser.ParseDir(fset, path, filter, 0)
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index eb7f1a4b78..37cf03594f 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -234,10 +234,13 @@ type imethod struct {
// interfaceType represents an interface type.
type interfaceType struct {
rtype
- pkgPath name // import path
- methods []imethod // sorted by hash
+ pkgPath name // import path
+ expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
}
+func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
+func (t *interfaceType) isEmpty() bool { return cap(t.expMethods) == 0 }
+
// mapType represents a map type.
type mapType struct {
rtype
@@ -384,6 +387,44 @@ const (
kindMask = (1 << 5) - 1
)
+// String returns the name of k.
+func (k Kind) String() string {
+ if int(k) < len(kindNames) {
+ return kindNames[k]
+ }
+ return kindNames[0]
+}
+
+var kindNames = []string{
+ Invalid: "invalid",
+ Bool: "bool",
+ Int: "int",
+ Int8: "int8",
+ Int16: "int16",
+ Int32: "int32",
+ Int64: "int64",
+ Uint: "uint",
+ Uint8: "uint8",
+ Uint16: "uint16",
+ Uint32: "uint32",
+ Uint64: "uint64",
+ Uintptr: "uintptr",
+ Float32: "float32",
+ Float64: "float64",
+ Complex64: "complex64",
+ Complex128: "complex128",
+ Array: "array",
+ Chan: "chan",
+ Func: "func",
+ Interface: "interface",
+ Map: "map",
+ Ptr: "ptr",
+ Slice: "slice",
+ String: "string",
+ Struct: "struct",
+ UnsafePointer: "unsafe.Pointer",
+}
+
func (t *uncommonType) methods() []method {
if t.mcount == 0 {
return nil
@@ -657,7 +698,7 @@ func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
}
// NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.methods) }
+func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
@@ -694,9 +735,10 @@ func implements(T, V *rtype) bool {
return false
}
t := (*interfaceType)(unsafe.Pointer(T))
- if len(t.methods) == 0 {
+ if t.isEmpty() {
return true
}
+ tmethods := t.methods()
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
@@ -713,10 +755,11 @@ func implements(T, V *rtype) bool {
if V.Kind() == Interface {
v := (*interfaceType)(unsafe.Pointer(V))
i := 0
- for j := 0; j < len(v.methods); j++ {
- tm := &t.methods[i]
+ vmethods := v.methods()
+ for j := 0; j < len(vmethods); j++ {
+ tm := &tmethods[i]
tmName := t.nameOff(tm.name)
- vm := &v.methods[j]
+ vm := &vmethods[j]
vmName := V.nameOff(vm.name)
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
if !tmName.isExported() {
@@ -732,7 +775,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(t.methods) {
+ if i++; i >= len(tmethods) {
return true
}
}
@@ -747,7 +790,7 @@ func implements(T, V *rtype) bool {
i := 0
vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ {
- tm := &t.methods[i]
+ tm := &tmethods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j]
vmName := V.nameOff(vm.name)
@@ -765,7 +808,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(t.methods) {
+ if i++; i >= len(tmethods) {
return true
}
}
@@ -859,7 +902,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case Interface:
t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V))
- if len(t.methods) == 0 && len(v.methods) == 0 {
+ if t.isEmpty() && v.isEmpty() {
return true
}
// Might have the same methods but still
@@ -924,3 +967,11 @@ func toType(t *rtype) Type {
func ifaceIndir(t *rtype) bool {
return t.kind&kindDirectIface == 0
}
+
+func isEmptyIface(t *rtype) bool {
+ if t.Kind() != Interface {
+ return false
+ }
+ tt := (*interfaceType)(unsafe.Pointer(t))
+ return tt.isEmpty()
+}
diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go
index 85beea606c..fb0ec77b58 100644
--- a/src/internal/reflectlite/value.go
+++ b/src/internal/reflectlite/value.go
@@ -160,7 +160,10 @@ type ValueError struct {
}
func (e *ValueError) Error() string {
- return "reflect: call of " + e.Method + " on zero Value"
+ if e.Kind == 0 {
+ return "reflect: call of " + e.Method + " on zero Value"
+ }
+ return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
}
// methodName returns the name of the calling method,
@@ -225,7 +228,7 @@ func (v Value) Elem() Value {
switch k {
case Interface:
var eface interface{}
- if v.typ.NumMethod() == 0 {
+ if isEmptyIface(v.typ) {
eface = *(*interface{})(v.ptr)
} else {
eface = (interface{})(*(*interface {
@@ -430,7 +433,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
return Value{dst, nil, flag(Interface)}
}
x := valueInterface(v)
- if dst.NumMethod() == 0 {
+ if isEmptyIface(dst) {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go
index cc3d0c774b..612c48f084 100644
--- a/src/internal/syscall/windows/registry/key.go
+++ b/src/internal/syscall/windows/registry/key.go
@@ -25,10 +25,7 @@
//
package registry
-import (
- "io"
- "syscall"
-)
+import "syscall"
const (
// Registry key security and access rights.
@@ -90,20 +87,13 @@ func OpenKey(k Key, path string, access uint32) (Key, error) {
}
// ReadSubKeyNames returns the names of subkeys of key k.
-// The parameter n controls the number of returned names,
-// analogous to the way os.File.Readdirnames works.
-func (k Key) ReadSubKeyNames(n int) ([]string, error) {
+func (k Key) ReadSubKeyNames() ([]string, error) {
names := make([]string, 0)
// Registry key size limit is 255 bytes and described there:
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
buf := make([]uint16, 256) //plus extra room for terminating zero byte
loopItems:
for i := uint32(0); ; i++ {
- if n > 0 {
- if len(names) == n {
- return names, nil
- }
- }
l := uint32(len(buf))
for {
err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
@@ -123,9 +113,6 @@ loopItems:
}
names = append(names, syscall.UTF16ToString(buf[:l]))
}
- if n > len(names) {
- return names, io.EOF
- }
return names, nil
}
diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go
index 8227232c70..5797162900 100644
--- a/src/internal/syscall/windows/registry/registry_test.go
+++ b/src/internal/syscall/windows/registry/registry_test.go
@@ -34,7 +34,7 @@ func TestReadSubKeyNames(t *testing.T) {
}
defer k.Close()
- names, err := k.ReadSubKeyNames(-1)
+ names, err := k.ReadSubKeyNames()
if err != nil {
t.Fatal(err)
}
@@ -190,7 +190,7 @@ func setValues(t *testing.T, k registry.Key) {
}
func enumerateValues(t *testing.T, k registry.Key) {
- names, err := k.ReadValueNames(-1)
+ names, err := k.ReadValueNames()
if err != nil {
t.Error(err)
return
@@ -480,7 +480,7 @@ func deleteValues(t *testing.T, k registry.Key) {
continue
}
}
- names, err := k.ReadValueNames(-1)
+ names, err := k.ReadValueNames()
if err != nil {
t.Error(err)
return
diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go
index bf8ab00759..dc3930a6bc 100644
--- a/src/internal/syscall/windows/registry/value.go
+++ b/src/internal/syscall/windows/registry/value.go
@@ -8,7 +8,6 @@ package registry
import (
"errors"
- "io"
"syscall"
"unicode/utf16"
"unsafe"
@@ -341,9 +340,7 @@ func (k Key) DeleteValue(name string) error {
}
// ReadValueNames returns the value names of key k.
-// The parameter n controls the number of returned names,
-// analogous to the way os.File.Readdirnames works.
-func (k Key) ReadValueNames(n int) ([]string, error) {
+func (k Key) ReadValueNames() ([]string, error) {
ki, err := k.Stat()
if err != nil {
return nil, err
@@ -352,11 +349,6 @@ func (k Key) ReadValueNames(n int) ([]string, error) {
buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character
loopItems:
for i := uint32(0); ; i++ {
- if n > 0 {
- if len(names) == n {
- return names, nil
- }
- }
l := uint32(len(buf))
for {
err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
@@ -376,8 +368,5 @@ loopItems:
}
names = append(names, syscall.UTF16ToString(buf[:l]))
}
- if n > len(names) {
- return names, io.EOF
- }
return names, nil
}
diff --git a/src/internal/sysinfo/sysinfo.go b/src/internal/sysinfo/sysinfo.go
new file mode 100644
index 0000000000..961be7abae
--- /dev/null
+++ b/src/internal/sysinfo/sysinfo.go
@@ -0,0 +1,31 @@
+// Copyright 2020 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 sysinfo implements high level hardware information gathering
+// that can be used for debugging or information purposes.
+package sysinfo
+
+import (
+ internalcpu "internal/cpu"
+ "sync"
+)
+
+type cpuInfo struct {
+ once sync.Once
+ name string
+}
+
+var CPU cpuInfo
+
+func (cpu *cpuInfo) Name() string {
+ cpu.once.Do(func() {
+ // Try to get the information from internal/cpu.
+ if name := internalcpu.Name(); name != "" {
+ cpu.name = name
+ return
+ }
+ // TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
+ })
+ return cpu.name
+}
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index cfb033b2a2..0ee6355ee3 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -43,12 +43,8 @@ func HasGoBuild() bool {
return false
}
switch runtime.GOOS {
- case "android", "js":
+ case "android", "js", "ios":
return false
- case "darwin", "ios":
- if runtime.GOARCH == "arm64" {
- return false
- }
}
return true
}
@@ -122,12 +118,8 @@ func GoTool() (string, error) {
// using os.StartProcess or (more commonly) exec.Command.
func HasExec() bool {
switch runtime.GOOS {
- case "js":
+ case "js", "ios":
return false
- case "darwin", "ios":
- if runtime.GOARCH == "arm64" {
- return false
- }
}
return true
}
@@ -135,10 +127,8 @@ func HasExec() bool {
// HasSrc reports whether the entire source tree is available under GOROOT.
func HasSrc() bool {
switch runtime.GOOS {
- case "darwin", "ios":
- if runtime.GOARCH == "arm64" {
- return false
- }
+ case "ios":
+ return false
}
return true
}
@@ -202,6 +192,32 @@ func MustHaveCGO(t testing.TB) {
}
}
+// CanInternalLink reports whether the current system can link programs with
+// internal linking.
+// (This is the opposite of cmd/internal/sys.MustLinkExternal. Keep them in sync.)
+func CanInternalLink() bool {
+ switch runtime.GOOS {
+ case "android":
+ if runtime.GOARCH != "arm64" {
+ return false
+ }
+ case "darwin", "ios":
+ if runtime.GOARCH == "arm64" {
+ return false
+ }
+ }
+ return true
+}
+
+// MustInternalLink checks that the current system can link programs with internal
+// linking.
+// If not, MustInternalLink calls t.Skip with an explanation.
+func MustInternalLink(t testing.TB) {
+ if !CanInternalLink() {
+ t.Skipf("skipping test: internal linking on %s/%s is not supported", runtime.GOOS, runtime.GOARCH)
+ }
+}
+
// HasSymlink reports whether the current system can use os.Symlink.
func HasSymlink() bool {
ok, _ := hasSymlink()