Compare commits
10 Commits
97d6430458
...
e3fbb58954
| Author | SHA1 | Date | |
|---|---|---|---|
| e3fbb58954 | |||
|
|
26d5e16075 | ||
|
|
6b7763407c | ||
|
|
3fc4af70d0 | ||
|
|
c43088c7a6 | ||
|
|
3d7681ebab | ||
|
|
a8f99ef1f6 | ||
|
|
96d6d38872 | ||
|
|
e30e65f7a8 | ||
|
|
d3651c5888 |
@@ -461,14 +461,9 @@ func (ctxt *Link) domacho() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
Exitf("%v", err)
|
Exitf("%v", err)
|
||||||
}
|
}
|
||||||
if load != nil {
|
if load != nil && load.platform != PLATFORM_MACOS {
|
||||||
machoPlatform = load.platform
|
|
||||||
ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
|
ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
|
||||||
copy(ml.data, load.cmd.data)
|
copy(ml.data, load.cmd.data)
|
||||||
if machoPlatform == PLATFORM_MACOS {
|
|
||||||
ml.data[1] = macOS.version()
|
|
||||||
ml.data[2] = macSDK.version()
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -477,7 +472,7 @@ func (ctxt *Link) domacho() {
|
|||||||
if buildcfg.GOOS == "ios" {
|
if buildcfg.GOOS == "ios" {
|
||||||
machoPlatform = PLATFORM_IOS
|
machoPlatform = PLATFORM_IOS
|
||||||
}
|
}
|
||||||
if ctxt.LinkMode == LinkInternal && machoPlatform == PLATFORM_MACOS {
|
if load == nil && machoPlatform == PLATFORM_MACOS {
|
||||||
ml := newMachoLoad(ctxt.Arch, imacho.LC_BUILD_VERSION, 4)
|
ml := newMachoLoad(ctxt.Arch, imacho.LC_BUILD_VERSION, 4)
|
||||||
ml.data[0] = uint32(machoPlatform)
|
ml.data[0] = uint32(machoPlatform)
|
||||||
ml.data[1] = macOS.version()
|
ml.data[1] = macOS.version()
|
||||||
|
|||||||
28
src/go/printer/math.go
Normal file
28
src/go/printer/math.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2026 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package printer
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// log2ish returns a crude approximation to log₂(x).
|
||||||
|
// The result is only used for heuristic alignment decisions and should
|
||||||
|
// not be used where precision matters.
|
||||||
|
// The approximation is guaranteed to produce identical results
|
||||||
|
// across all architectures.
|
||||||
|
func log2ish(x float64) float64 {
|
||||||
|
f, e := math.Frexp(x)
|
||||||
|
return float64(e) + 2*(f-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// exp2ish returns a crude approximation to 2**x.
|
||||||
|
// The result is only used for heuristic alignment decisions and should
|
||||||
|
// not be used where precision matters.
|
||||||
|
// The approximation is guaranteed to produce identical results
|
||||||
|
// across all architectures.
|
||||||
|
func exp2ish(x float64) float64 {
|
||||||
|
n := math.Floor(x)
|
||||||
|
f := x - n
|
||||||
|
return math.Ldexp(1+f, int(n))
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ package printer
|
|||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"math"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
@@ -183,9 +182,9 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||||||
|
|
||||||
// We use the ratio between the geometric mean of the previous key sizes and
|
// We use the ratio between the geometric mean of the previous key sizes and
|
||||||
// the current size to determine if there should be a break in the alignment.
|
// the current size to determine if there should be a break in the alignment.
|
||||||
// To compute the geometric mean we accumulate the ln(size) values (lnsum)
|
// To compute the geometric mean we accumulate the log₂(size) values (log2sum)
|
||||||
// and the number of sizes included (count).
|
// and the number of sizes included (count).
|
||||||
lnsum := 0.0
|
log2sum := 0.0
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
// print all list elements
|
// print all list elements
|
||||||
@@ -228,8 +227,8 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||||||
if count == 0 || prevSize <= smallSize && size <= smallSize {
|
if count == 0 || prevSize <= smallSize && size <= smallSize {
|
||||||
useFF = false
|
useFF = false
|
||||||
} else {
|
} else {
|
||||||
const r = 2.5 // threshold
|
const r = 2.5 // threshold
|
||||||
geomean := math.Exp(lnsum / float64(count)) // count > 0
|
geomean := exp2ish(log2sum / float64(count)) // count > 0
|
||||||
ratio := float64(size) / geomean
|
ratio := float64(size) / geomean
|
||||||
useFF = r*ratio <= 1 || r <= ratio
|
useFF = r*ratio <= 1 || r <= ratio
|
||||||
}
|
}
|
||||||
@@ -260,7 +259,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||||||
// the section), reset the geomean variables since we are
|
// the section), reset the geomean variables since we are
|
||||||
// starting a new group of elements with the next element.
|
// starting a new group of elements with the next element.
|
||||||
if nbreaks > 1 {
|
if nbreaks > 1 {
|
||||||
lnsum = 0
|
log2sum = 0
|
||||||
count = 0
|
count = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,7 +283,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
lnsum += math.Log(float64(size))
|
log2sum += log2ish(float64(size))
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
src/go/printer/testdata/alignment.golden
vendored
7
src/go/printer/testdata/alignment.golden
vendored
@@ -170,3 +170,10 @@ var _ = S{
|
|||||||
F1____: []string{},
|
F1____: []string{},
|
||||||
F2: []string{},
|
F2: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #77959: formatting must be consistent across architectures.
|
||||||
|
var _ = []any{
|
||||||
|
(expr_size_95_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(0), // 0
|
||||||
|
(expr_size_38_xxxxxxxxxxxxxxxxxxxx)(0), // 1
|
||||||
|
(*expr_size_126_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(nil), // 2
|
||||||
|
}
|
||||||
|
|||||||
7
src/go/printer/testdata/alignment.input
vendored
7
src/go/printer/testdata/alignment.input
vendored
@@ -177,3 +177,10 @@ var _ = S{
|
|||||||
},
|
},
|
||||||
F2: []string{},
|
F2: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #77959: formatting must be consistent across architectures.
|
||||||
|
var _ = []any{
|
||||||
|
(expr_size_95_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(0), // 0
|
||||||
|
(expr_size_38_xxxxxxxxxxxxxxxxxxxx)(0), // 1
|
||||||
|
(*expr_size_126_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(nil), // 2
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ func SendFile(fd *FD, src uintptr, size int64) (written int64, err error, handle
|
|||||||
chunkSize = size
|
chunkSize = size
|
||||||
}
|
}
|
||||||
|
|
||||||
fd.setOffset(startpos + written)
|
|
||||||
n, err := fd.execIO('w', func(o *operation) (uint32, error) {
|
n, err := fd.execIO('w', func(o *operation) (uint32, error) {
|
||||||
|
o.setOffset(startpos + written)
|
||||||
err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
|
err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build arm64 || loong64
|
//go:build arm64 || loong64 || riscv64
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !arm64 && !loong64
|
//go:build !arm64 && !loong64 && !riscv64
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build amd64 || arm64 || loong64 || s390x
|
//go:build amd64 || arm64 || loong64 || riscv64 || s390x
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !amd64 && !arm64 && !loong64 && !s390x
|
//go:build !amd64 && !arm64 && !loong64 && !riscv64 && !s390x
|
||||||
|
|
||||||
package math
|
package math
|
||||||
|
|
||||||
|
|||||||
236
src/math/exp_riscv64.s
Normal file
236
src/math/exp_riscv64.s
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// Copyright 2026 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define NearZero 0x3e30000000000000 // 2**-28
|
||||||
|
#define PosInf 0x7ff0000000000000
|
||||||
|
#define FracMask 0x000fffffffffffff
|
||||||
|
#define C1 0x3cb0000000000000 // 2**-52
|
||||||
|
|
||||||
|
DATA exprodata<>+0(SB)/8, $0.0
|
||||||
|
DATA exprodata<>+8(SB)/8, $0.5
|
||||||
|
DATA exprodata<>+16(SB)/8, $1.0
|
||||||
|
DATA exprodata<>+24(SB)/8, $2.0
|
||||||
|
DATA exprodata<>+32(SB)/8, $6.93147180369123816490e-01 // Ln2Hi
|
||||||
|
DATA exprodata<>+40(SB)/8, $1.90821492927058770002e-10 // Ln2Lo
|
||||||
|
DATA exprodata<>+48(SB)/8, $1.44269504088896338700e+00 // Log2e
|
||||||
|
DATA exprodata<>+56(SB)/8, $7.09782712893383973096e+02 // Overflow
|
||||||
|
DATA exprodata<>+64(SB)/8, $-7.45133219101941108420e+02 // Underflow
|
||||||
|
DATA exprodata<>+72(SB)/8, $1.0239999999999999e+03 // Overflow2
|
||||||
|
DATA exprodata<>+80(SB)/8, $-1.0740e+03 // Underflow2
|
||||||
|
DATA exprodata<>+88(SB)/8, $3.7252902984619141e-09 // NearZero
|
||||||
|
GLOBL exprodata<>+0(SB), NOPTR|RODATA, $96
|
||||||
|
|
||||||
|
DATA expmultirodata<>+0(SB)/8, $1.66666666666666657415e-01 // P1
|
||||||
|
DATA expmultirodata<>+8(SB)/8, $-2.77777777770155933842e-03 // P2
|
||||||
|
DATA expmultirodata<>+16(SB)/8, $6.61375632143793436117e-05 // P3
|
||||||
|
DATA expmultirodata<>+24(SB)/8, $-1.65339022054652515390e-06 // P4
|
||||||
|
DATA expmultirodata<>+32(SB)/8, $4.13813679705723846039e-08 // P5
|
||||||
|
GLOBL expmultirodata<>+0(SB), NOPTR|RODATA, $40
|
||||||
|
|
||||||
|
// Exp returns e**x, the base-e exponential of x.
|
||||||
|
// This is an assembly implementation of the method used for function Exp in file exp.go.
|
||||||
|
//
|
||||||
|
// func Exp(x float64) float64
|
||||||
|
TEXT ·archExp(SB),$0-16
|
||||||
|
MOVD x+0(FP), F0 // F0 = x
|
||||||
|
|
||||||
|
MOV $exprodata<>+0(SB), X5
|
||||||
|
MOVD 56(X5), F1 // Overflow
|
||||||
|
MOVD 64(X5), F2 // Underflow
|
||||||
|
MOVD 88(X5), F3 // NearZero
|
||||||
|
MOVD 16(X5), F17 // 1.0
|
||||||
|
|
||||||
|
FEQD F0, F0, X7
|
||||||
|
BEQ X0, X7, isNaN // x = NaN, return NaN
|
||||||
|
|
||||||
|
FLTD F0, F1, X7
|
||||||
|
BNE X0, X7, overflow // x > Overflow, return PosInf
|
||||||
|
|
||||||
|
FLTD F2, F0, X7
|
||||||
|
BNE X0, X7, underflow // x < Underflow, return 0
|
||||||
|
|
||||||
|
FABSD F0, F5
|
||||||
|
FLTD F3, F5, X7
|
||||||
|
BNE X0, X7, nearzero // fabs(x) < NearZero, return 1 + x
|
||||||
|
|
||||||
|
// argument reduction, x = k*ln2 + r, |r| <= 0.5*ln2
|
||||||
|
// computed as r = hi - lo for extra precision.
|
||||||
|
MOVD 0(X5), F5
|
||||||
|
MOVD 8(X5), F3
|
||||||
|
MOVD 48(X5), F2
|
||||||
|
FLTD F0, F5, X7
|
||||||
|
BNE X0, X7, add // x > 0
|
||||||
|
sub:
|
||||||
|
FMSUBD F0, F2, F3, F3 // Log2e*x - 0.5
|
||||||
|
JMP 2(PC)
|
||||||
|
add:
|
||||||
|
FMADDD F0, F2, F3, F3 // Log2e*x + 0.5
|
||||||
|
|
||||||
|
FCVTLD.RTZ F3, X16 // float64 -> int64
|
||||||
|
FCVTDL X16, F3 // int64 -> float64
|
||||||
|
|
||||||
|
MOVD 32(X5), F4
|
||||||
|
MOVD 40(X5), F5
|
||||||
|
FNMSUBD F3, F4, F0, F4
|
||||||
|
FMULD F3, F5, F5
|
||||||
|
FSUBD F5, F4, F6
|
||||||
|
FMULD F6, F6, F7
|
||||||
|
|
||||||
|
// compute c
|
||||||
|
// r=(FMA x y z) -> FMADDD z, y, x, r
|
||||||
|
// r=(FMA x y z) -> FMADDD x, y, z, r
|
||||||
|
MOV $expmultirodata<>+0(SB), X6
|
||||||
|
MOVD 32(X6), F8
|
||||||
|
MOVD 24(X6), F9
|
||||||
|
FMADDD F7, F8, F9, F13
|
||||||
|
MOVD 16(X6), F10
|
||||||
|
FMADDD F7, F13, F10, F13
|
||||||
|
MOVD 8(X6), F11
|
||||||
|
FMADDD F7, F13, F11, F13
|
||||||
|
MOVD 0(X6), F12
|
||||||
|
FMADDD F7, F13, F12, F13
|
||||||
|
FNMSUBD F21, F8, F6, F8
|
||||||
|
|
||||||
|
// compute y
|
||||||
|
MOVD 24(X5), F14
|
||||||
|
FSUBD F8, F14, F14
|
||||||
|
FMULD F6, F8, F15
|
||||||
|
FDIVD F14, F15, F15
|
||||||
|
FSUBD F15, F5, F15
|
||||||
|
FSUBD F4, F15, F15
|
||||||
|
FSUBD F15, F17, F16
|
||||||
|
|
||||||
|
// inline Ldexp(y, k), benefit:
|
||||||
|
// 1, no parameter pass overhead.
|
||||||
|
// 2, skip unnecessary checks for Inf/NaN/Zero
|
||||||
|
MOVD F16, X15
|
||||||
|
MOV $FracMask, X20
|
||||||
|
AND X20, X15, X17 // fraction
|
||||||
|
SRL $52, X15, X18 // exponent
|
||||||
|
ADD X16, X18
|
||||||
|
MOV $1, X21
|
||||||
|
BGE X18, X21, normal
|
||||||
|
ADD $52, X18 // denormal
|
||||||
|
MOV $C1, X19
|
||||||
|
MOVD X19, F17
|
||||||
|
normal:
|
||||||
|
SLL $52, X18
|
||||||
|
OR X18, X17, X15
|
||||||
|
MOVD X15, F0
|
||||||
|
FMULD F17, F0, F0 // return m * x
|
||||||
|
MOVD F0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
nearzero:
|
||||||
|
FADDD F17, F0, F0
|
||||||
|
isNaN:
|
||||||
|
MOVD F0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
underflow:
|
||||||
|
MOV X0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
overflow:
|
||||||
|
MOV $PosInf, X15
|
||||||
|
MOV X15, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
|
||||||
|
// Exp2 returns 2**x, the base-2 exponential of x.
|
||||||
|
// This is an assembly implementation of the method used for function Exp2 in file exp.go.
|
||||||
|
//
|
||||||
|
// func Exp2(x float64) float64
|
||||||
|
TEXT ·archExp2(SB),$0-16
|
||||||
|
MOVD x+0(FP), F0 // F0 = x
|
||||||
|
|
||||||
|
MOV $exprodata<>+0(SB), X5
|
||||||
|
MOVD 72(X5), F1 // Overflow2
|
||||||
|
MOVD 80(X5), F2 // Underflow2
|
||||||
|
MOVD 88(X5), F3 // NearZero
|
||||||
|
|
||||||
|
FEQD F0, F0, X7
|
||||||
|
BEQ X0, X7, isNaN // x = NaN, return NaN
|
||||||
|
|
||||||
|
FLTD F0, F1, X7
|
||||||
|
BNE X0, X7, overflow // x > Overflow, return PosInf
|
||||||
|
|
||||||
|
FLTD F2, F0, X7
|
||||||
|
BNE X0, X7, underflow // x < Underflow, return 0
|
||||||
|
|
||||||
|
// argument reduction; x = r*lg(e) + k with |r| <= ln(2)/2
|
||||||
|
// computed as r = hi - lo for extra precision.
|
||||||
|
MOVD 0(X5), F10
|
||||||
|
MOVD 8(X5), F2
|
||||||
|
FLTD F0, F10, X7
|
||||||
|
BNE X0, X7, add
|
||||||
|
sub:
|
||||||
|
FSUBD F2, F0, F3 // x - 0.5
|
||||||
|
JMP 2(PC)
|
||||||
|
add:
|
||||||
|
FADDD F2, F0, F3 // x + 0.5
|
||||||
|
|
||||||
|
FCVTLD.RTZ F3, X16
|
||||||
|
FCVTDL X16, F3
|
||||||
|
|
||||||
|
MOVD 32(X5), F4
|
||||||
|
MOVD 40(X5), F5
|
||||||
|
FSUBD F3, F0, F3
|
||||||
|
FMULD F3, F4, F4
|
||||||
|
FNMSUBD F5, F3, F10, F5
|
||||||
|
FSUBD F5, F4, F6
|
||||||
|
FMULD F6, F6, F7
|
||||||
|
|
||||||
|
// compute c
|
||||||
|
MOV $expmultirodata<>+0(SB), X6
|
||||||
|
MOVD 32(X6), F13
|
||||||
|
MOVD 24(X6), F9
|
||||||
|
FMADDD F7, F13, F9, F13
|
||||||
|
MOVD 16(X6), F10
|
||||||
|
FMADDD F7, F13, F10, F13
|
||||||
|
MOVD 8(X6), F11
|
||||||
|
FMADDD F7, F13, F11, F13
|
||||||
|
MOVD 0(X6), F12
|
||||||
|
FMADDD F7, F13, F12, F13
|
||||||
|
FNMSUBD F7, F13, F6, F13
|
||||||
|
|
||||||
|
// compute y
|
||||||
|
MOVD 24(X5), F14
|
||||||
|
FSUBD F13, F14, F14
|
||||||
|
FMULD F6, F13, F15
|
||||||
|
FDIVD F14, F15, F15
|
||||||
|
|
||||||
|
MOVD 16(X5), F17
|
||||||
|
FSUBD F15, F5, F15
|
||||||
|
FSUBD F4, F15, F15
|
||||||
|
FSUBD F15, F17, F16
|
||||||
|
|
||||||
|
// inline Ldexp(y, k), benefit:
|
||||||
|
// 1, no parameter pass overhead.
|
||||||
|
// 2, skip unnecessary checks for Inf/NaN/Zero
|
||||||
|
MOVD F16, X15
|
||||||
|
MOV $FracMask, X20
|
||||||
|
SRL $52, X15, X18 // exponent
|
||||||
|
AND X20, X15, X17 // fraction
|
||||||
|
ADD X16, X18
|
||||||
|
MOV $1, X21
|
||||||
|
BGE X18, X21, normal
|
||||||
|
|
||||||
|
ADD $52, X18 // denormal
|
||||||
|
MOV $C1, X19
|
||||||
|
MOVD X19, F17
|
||||||
|
normal:
|
||||||
|
SLL $52, X18
|
||||||
|
OR X18, X17, X15
|
||||||
|
MOVD X15, F0
|
||||||
|
FMULD F17, F0, F0
|
||||||
|
isNaN:
|
||||||
|
MOVD F0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
underflow:
|
||||||
|
MOV X0, ret+8(FP)
|
||||||
|
RET
|
||||||
|
overflow:
|
||||||
|
MOV $PosInf, X15
|
||||||
|
MOV X15, ret+8(FP)
|
||||||
|
RET
|
||||||
@@ -558,6 +558,11 @@ const defaultUserAgent = "Go-http-client/1.1"
|
|||||||
// If Body is present, Content-Length is <= 0 and [Request.TransferEncoding]
|
// If Body is present, Content-Length is <= 0 and [Request.TransferEncoding]
|
||||||
// hasn't been set to "identity", Write adds "Transfer-Encoding:
|
// hasn't been set to "identity", Write adds "Transfer-Encoding:
|
||||||
// chunked" to the header. Body is closed after it is sent.
|
// chunked" to the header. Body is closed after it is sent.
|
||||||
|
//
|
||||||
|
// Header values for Host, Content-Length, Transfer-Encoding,
|
||||||
|
// and Trailer are not used; these are derived from other Request fields.
|
||||||
|
// If the Header does not contain a User-Agent value, Write uses
|
||||||
|
// "Go-http-client/1.1".
|
||||||
func (r *Request) Write(w io.Writer) error {
|
func (r *Request) Write(w io.Writer) error {
|
||||||
return r.write(w, false, nil, nil)
|
return r.write(w, false, nil, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,9 +388,8 @@ type dialClientConner interface {
|
|||||||
// If HTTP/3 proxies are not supported, DialClientConn should return
|
// If HTTP/3 proxies are not supported, DialClientConn should return
|
||||||
// an error wrapping [errors.ErrUnsupported].
|
// an error wrapping [errors.ErrUnsupported].
|
||||||
//
|
//
|
||||||
// The RoundTripper returned by DialClientConn may implement
|
// The RoundTripper returned by DialClientConn must also implement the
|
||||||
// any of the following methods to support the [ClientConn]
|
// following methods to support [ClientConn] methods of the same name:
|
||||||
// method of the same name:
|
|
||||||
// Close() error
|
// Close() error
|
||||||
// Err() error
|
// Err() error
|
||||||
// Reserve() error
|
// Reserve() error
|
||||||
@@ -411,6 +410,16 @@ type dialClientConner interface {
|
|||||||
DialClientConn(ctx context.Context, address string, proxy *url.URL, internalStateHook func()) (RoundTripper, error)
|
DialClientConn(ctx context.Context, address string, proxy *url.URL, internalStateHook func()) (RoundTripper, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type closeIdleConnectionser interface {
|
||||||
|
// CloseIdleConnections is called by Transport.CloseIdleConnections.
|
||||||
|
//
|
||||||
|
// The transport will close idle connections created with DialClientConn
|
||||||
|
// before calling this method. The HTTP/3 transport should not attempt to
|
||||||
|
// close idle connections, but may clean up shared resources such as UDP
|
||||||
|
// sockets if no connections remain.
|
||||||
|
CloseIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
// h2Transport is the interface we expect to be able to call from
|
// h2Transport is the interface we expect to be able to call from
|
||||||
// net/http against an *http2.Transport that's either bundled into
|
// net/http against an *http2.Transport that's either bundled into
|
||||||
// h2_bundle.go or supplied by the user via x/net/http2.
|
// h2_bundle.go or supplied by the user via x/net/http2.
|
||||||
@@ -956,6 +965,9 @@ func (t *Transport) CloseIdleConnections() {
|
|||||||
if t2 := t.h2transport; t2 != nil {
|
if t2 := t.h2transport; t2 != nil {
|
||||||
t2.CloseIdleConnections()
|
t2.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
if cc, ok := t.h3transport.(closeIdleConnectionser); ok {
|
||||||
|
cc.CloseIdleConnections()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepareTransportCancel sets up state to convert Transport.CancelRequest into context cancelation.
|
// prepareTransportCancel sets up state to convert Transport.CancelRequest into context cancelation.
|
||||||
@@ -3088,11 +3100,16 @@ func (pc *persistConn) closeLocked(err error) {
|
|||||||
pc.t.decConnsPerHost(pc.cacheKey)
|
pc.t.decConnsPerHost(pc.cacheKey)
|
||||||
// Close HTTP/1 (pc.alt == nil) connection.
|
// Close HTTP/1 (pc.alt == nil) connection.
|
||||||
// HTTP/2 closes its connection itself.
|
// HTTP/2 closes its connection itself.
|
||||||
|
// Close HTTP/3 connection if it implements io.Closer.
|
||||||
if pc.alt == nil {
|
if pc.alt == nil {
|
||||||
if err != errCallerOwnsConn {
|
if err != errCallerOwnsConn {
|
||||||
pc.conn.Close()
|
pc.conn.Close()
|
||||||
}
|
}
|
||||||
close(pc.closech)
|
close(pc.closech)
|
||||||
|
} else {
|
||||||
|
if cc, ok := pc.alt.(io.Closer); ok {
|
||||||
|
cc.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pc.mutateHeaderFunc = nil
|
pc.mutateHeaderFunc = nil
|
||||||
|
|||||||
@@ -132,6 +132,10 @@ func (ip IP) IsLoopback() bool {
|
|||||||
|
|
||||||
// IsPrivate reports whether ip is a private address, according to
|
// IsPrivate reports whether ip is a private address, according to
|
||||||
// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
|
// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
|
||||||
|
// That is, it reports whether ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7.
|
||||||
|
//
|
||||||
|
// IsPrivate does not describe a security property of addresses,
|
||||||
|
// and should not be used for access control.
|
||||||
func (ip IP) IsPrivate() bool {
|
func (ip IP) IsPrivate() bool {
|
||||||
if ip4 := ip.To4(); ip4 != nil {
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
// Following RFC 1918, Section 3. Private Address Space which says:
|
// Following RFC 1918, Section 3. Private Address Space which says:
|
||||||
|
|||||||
@@ -637,6 +637,9 @@ func (ip Addr) IsGlobalUnicast() bool {
|
|||||||
// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
|
// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
|
||||||
// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
|
// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
|
||||||
// same as [net.IP.IsPrivate].
|
// same as [net.IP.IsPrivate].
|
||||||
|
//
|
||||||
|
// IsPrivate does not describe a security property of addresses,
|
||||||
|
// and should not be used for access control.
|
||||||
func (ip Addr) IsPrivate() bool {
|
func (ip Addr) IsPrivate() bool {
|
||||||
if ip.Is4In6() {
|
if ip.Is4In6() {
|
||||||
ip = ip.Unmap()
|
ip = ip.Unmap()
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var testHookSupportsSendfile func() bool
|
||||||
|
|
||||||
// sendFile copies the contents of r to c using the sendfile
|
// sendFile copies the contents of r to c using the sendfile
|
||||||
// system call to minimize copies.
|
// system call to minimize copies.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ package net
|
|||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
|
var testHookSupportsSendfile func() bool
|
||||||
|
|
||||||
func supportsSendfile() bool {
|
func supportsSendfile() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,16 @@ const (
|
|||||||
newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
|
newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func hookSupportsSendfile(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
origHook := testHookSupportsSendfile
|
||||||
|
testHookSupportsSendfile = func() bool { return true }
|
||||||
|
t.Cleanup(func() {
|
||||||
|
testHookSupportsSendfile = origHook
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// expectSendfile runs f, and verifies that internal/poll.SendFile successfully handles
|
// expectSendfile runs f, and verifies that internal/poll.SendFile successfully handles
|
||||||
// a write to wantConn during f's execution.
|
// a write to wantConn during f's execution.
|
||||||
//
|
//
|
||||||
@@ -35,6 +45,7 @@ const (
|
|||||||
// expect a call to SendFile.
|
// expect a call to SendFile.
|
||||||
func expectSendfile(t *testing.T, wantConn Conn, f func()) {
|
func expectSendfile(t *testing.T, wantConn Conn, f func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
hookSupportsSendfile(t)
|
||||||
if !supportsSendfile() {
|
if !supportsSendfile() {
|
||||||
f()
|
f()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -12,5 +12,8 @@ import "internal/syscall/windows"
|
|||||||
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
|
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
|
||||||
// https://golang.org/issue/73746
|
// https://golang.org/issue/73746
|
||||||
func supportsSendfile() bool {
|
func supportsSendfile() bool {
|
||||||
|
if testHookSupportsSendfile != nil {
|
||||||
|
return testHookSupportsSendfile()
|
||||||
|
}
|
||||||
return windows.SupportUnlimitedTransmitFile()
|
return windows.SupportUnlimitedTransmitFile()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ package cgo
|
|||||||
#cgo netbsd LDFLAGS: -lpthread
|
#cgo netbsd LDFLAGS: -lpthread
|
||||||
#cgo openbsd LDFLAGS: -lpthread
|
#cgo openbsd LDFLAGS: -lpthread
|
||||||
#cgo aix LDFLAGS: -Wl,-berok
|
#cgo aix LDFLAGS: -Wl,-berok
|
||||||
#cgo solaris LDFLAGS: -lxnet
|
|
||||||
#cgo solaris LDFLAGS: -lsocket
|
|
||||||
|
|
||||||
// Use -fno-stack-protector to avoid problems locating the
|
// Use -fno-stack-protector to avoid problems locating the
|
||||||
// proper support functions. See issues #52919, #54313, #58385.
|
// proper support functions. See issues #52919, #54313, #58385.
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ import (
|
|||||||
// func main() {
|
// func main() {
|
||||||
// val := "hello Go"
|
// val := "hello Go"
|
||||||
// h := cgo.NewHandle(val)
|
// h := cgo.NewHandle(val)
|
||||||
|
// // In this example, unsafe.Pointer(&h) is valid because myprint
|
||||||
|
// // does not keep a copy of the pointer. If the C code keeps the
|
||||||
|
// // pointer after the call returns, use runtime.Pinner to pin it.
|
||||||
// C.myprint(unsafe.Pointer(&h))
|
// C.myprint(unsafe.Pointer(&h))
|
||||||
// // Output: hello Go
|
// // Output: hello Go
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ func Pipe2(p []int, flags int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:cgo_ldflag "-lxnet"
|
||||||
|
//go:cgo_ldflag "-lsocket"
|
||||||
|
|
||||||
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4
|
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4
|
||||||
|
|
||||||
func Accept4(fd int, flags int) (int, Sockaddr, error) {
|
func Accept4(fd int, flags int) (int, Sockaddr, error) {
|
||||||
|
|||||||
@@ -85,6 +85,28 @@ func TestTBHelperParallel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 72794.
|
||||||
|
func TestHelperRange(t *testing.T) {
|
||||||
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
||||||
|
rangeHelperHelper(t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestHelperRange$")
|
||||||
|
cmd = testenv.CleanCmdEnv(cmd)
|
||||||
|
cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
|
||||||
|
out, _ := cmd.CombinedOutput()
|
||||||
|
want := `--- FAIL: TestHelperRange \([^)]+\)
|
||||||
|
helperfuncs_test.go:139: range
|
||||||
|
helperfuncs_test.go:139: range
|
||||||
|
`
|
||||||
|
if !regexp.MustCompile(want).Match(out) {
|
||||||
|
t.Errorf("got output:\n\n%s\nwant matching:\n\n%s", out, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkTBHelper(b *testing.B) {
|
func BenchmarkTBHelper(b *testing.B) {
|
||||||
f1 := func() {
|
f1 := func() {
|
||||||
b.Helper()
|
b.Helper()
|
||||||
|
|||||||
@@ -122,3 +122,19 @@ func doPanic(t *testing.T, msg string) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
panic(msg)
|
panic(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rangeHelper(t *testing.T, msg string) {
|
||||||
|
t.Helper()
|
||||||
|
iter := func(yield func(int) bool) {
|
||||||
|
if yield(0) {
|
||||||
|
yield(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for range iter {
|
||||||
|
t.Error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rangeHelperHelper(t *testing.T) {
|
||||||
|
rangeHelper(t, "range")
|
||||||
|
}
|
||||||
|
|||||||
@@ -816,8 +816,15 @@ func (c *common) frameSkip(skip int) runtime.Frame {
|
|||||||
}
|
}
|
||||||
frames := runtime.CallersFrames(pc[:n])
|
frames := runtime.CallersFrames(pc[:n])
|
||||||
var firstFrame, prevFrame, frame runtime.Frame
|
var firstFrame, prevFrame, frame runtime.Frame
|
||||||
|
skipRange := false
|
||||||
for more := true; more; prevFrame = frame {
|
for more := true; more; prevFrame = frame {
|
||||||
frame, more = frames.Next()
|
frame, more = frames.Next()
|
||||||
|
if skipRange {
|
||||||
|
// Skip the iterator function when a helper
|
||||||
|
// functions does a range over function.
|
||||||
|
skipRange = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
if frame.Function == "runtime.gopanic" {
|
if frame.Function == "runtime.gopanic" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -861,7 +868,25 @@ func (c *common) frameSkip(skip int) runtime.Frame {
|
|||||||
c.helperNames[pcToName(pc)] = struct{}{}
|
c.helperNames[pcToName(pc)] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := c.helperNames[frame.Function]; !ok {
|
|
||||||
|
fnName := frame.Function
|
||||||
|
// Ignore trailing -rangeN used for iterator functions.
|
||||||
|
const rangeSuffix = "-range"
|
||||||
|
if suffixIdx := strings.LastIndex(fnName, rangeSuffix); suffixIdx > 0 {
|
||||||
|
ok := true
|
||||||
|
for i := suffixIdx + len(rangeSuffix); i < len(fnName); i++ {
|
||||||
|
if fnName[i] < '0' || fnName[i] > '9' {
|
||||||
|
ok = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
fnName = fnName[:suffixIdx]
|
||||||
|
skipRange = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := c.helperNames[fnName]; !ok {
|
||||||
// Found a frame that wasn't inside a helper function.
|
// Found a frame that wasn't inside a helper function.
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user