From 7aa4e5ac5fb3894e0eaf99fbc3704c32d934b199 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 7 Aug 2014 14:52:55 -0700 Subject: runtime: convert equality functions to Go LGTM=rsc R=rsc, khr CC=golang-codereviews https://golang.org/cl/121330043 --- src/pkg/runtime/alg.go | 100 +++++++++++++++++++ src/pkg/runtime/alg.goc | 210 ++++++++-------------------------------- src/pkg/runtime/asm_386.s | 43 +------- src/pkg/runtime/asm_amd64.s | 43 +------- src/pkg/runtime/asm_amd64p32.s | 43 +------- src/pkg/runtime/asm_arm.s | 54 +---------- src/pkg/runtime/hashmap.go | 37 ++++--- src/pkg/runtime/hashmap_fast.go | 12 +-- src/pkg/runtime/iface.go | 42 -------- src/pkg/runtime/iface.goc | 46 --------- src/pkg/runtime/runtime.h | 26 +++-- src/pkg/runtime/stubs.go | 13 +-- 12 files changed, 191 insertions(+), 478 deletions(-) (limited to 'src/pkg/runtime') diff --git a/src/pkg/runtime/alg.go b/src/pkg/runtime/alg.go index ea4156f1ed..409f0fa0c5 100644 --- a/src/pkg/runtime/alg.go +++ b/src/pkg/runtime/alg.go @@ -142,6 +142,106 @@ func nilinterhash(a *eface, s, h uintptr) uintptr { } } +func memequal(p, q unsafe.Pointer, size uintptr) bool { + if p == q { + return true + } + return memeq(p, q, size) +} + +func memequal0(p, q unsafe.Pointer, size uintptr) bool { + return true +} +func memequal8(p, q unsafe.Pointer, size uintptr) bool { + return *(*int8)(p) == *(*int8)(q) +} +func memequal16(p, q unsafe.Pointer, size uintptr) bool { + return *(*int16)(p) == *(*int16)(q) +} +func memequal32(p, q unsafe.Pointer, size uintptr) bool { + return *(*int32)(p) == *(*int32)(q) +} +func memequal64(p, q unsafe.Pointer, size uintptr) bool { + return *(*int64)(p) == *(*int64)(q) +} +func memequal128(p, q unsafe.Pointer, size uintptr) bool { + return *(*[2]int64)(p) == *(*[2]int64)(q) +} +func f32equal(p, q unsafe.Pointer, size uintptr) bool { + return *(*float32)(p) == *(*float32)(q) +} +func f64equal(p, q unsafe.Pointer, size uintptr) bool { + return *(*float64)(p) == *(*float64)(q) +} +func c64equal(p, q unsafe.Pointer, size uintptr) bool { + return *(*complex64)(p) == *(*complex64)(q) +} +func c128equal(p, q unsafe.Pointer, size uintptr) bool { + return *(*complex128)(p) == *(*complex128)(q) +} +func strequal(p, q unsafe.Pointer, size uintptr) bool { + return *(*string)(p) == *(*string)(q) +} +func interequal(p, q unsafe.Pointer, size uintptr) bool { + return ifaceeq(*(*interface { + f() + })(p), *(*interface { + f() + })(q)) +} +func nilinterequal(p, q unsafe.Pointer, size uintptr) bool { + return efaceeq(*(*interface{})(p), *(*interface{})(q)) +} +func efaceeq(p, q interface{}) bool { + x := (*eface)(unsafe.Pointer(&p)) + y := (*eface)(unsafe.Pointer(&q)) + t := x._type + if t != y._type { + return false + } + if t == nil { + return true + } + eq := goalg(t.alg).equal + if **(**uintptr)(unsafe.Pointer(&eq)) == noequalcode { + // calling noequal will panic too, + // but we can print a better error. + panic(errorString("comparing uncomparable type " + *t._string)) + } + if uintptr(t.size) <= ptrSize { + return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)), uintptr(t.size)) + } + return eq(x.data, y.data, uintptr(t.size)) +} +func ifaceeq(p, q interface { + f() +}) bool { + x := (*iface)(unsafe.Pointer(&p)) + y := (*iface)(unsafe.Pointer(&q)) + xtab := x.tab + if xtab != y.tab { + return false + } + if xtab == nil { + return true + } + t := xtab._type + eq := goalg(t.alg).equal + if **(**uintptr)(unsafe.Pointer(&eq)) == noequalcode { + // calling noequal will panic too, + // but we can print a better error. + panic(errorString("comparing uncomparable type " + *t._string)) + } + if uintptr(t.size) <= ptrSize { + return eq(noescape(unsafe.Pointer(&x.data)), noescape(unsafe.Pointer(&y.data)), uintptr(t.size)) + } + return eq(x.data, y.data, uintptr(t.size)) +} + +func noequal(p, q unsafe.Pointer, size uintptr) bool { + panic(errorString("comparing uncomparable types")) +} + // Testing adapters for hash quality tests (see hash_test.go) func haveGoodHash() bool { return use_aeshash diff --git a/src/pkg/runtime/alg.goc b/src/pkg/runtime/alg.goc index 6207ae526c..f9e8892929 100644 --- a/src/pkg/runtime/alg.goc +++ b/src/pkg/runtime/alg.goc @@ -9,16 +9,6 @@ package runtime bool runtime·use_aeshash; -void -runtime·memequal(bool *eq, uintptr s, void *a, void *b) -{ - if(a == b) { - *eq = 1; - return; - } - *eq = runtime·memeq(a, b, s); -} - void runtime·memprint(uintptr s, void *a) { @@ -52,15 +42,6 @@ runtime·memcopy(uintptr s, void *a, void *b) runtime·memmove(a, b, s); } -void -runtime·memequal0(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - USED(a); - USED(b); - *eq = true; -} - void runtime·memcopy0(uintptr s, void *a, void *b) { @@ -69,13 +50,6 @@ runtime·memcopy0(uintptr s, void *a, void *b) USED(b); } -void -runtime·memequal8(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(uint8*)a == *(uint8*)b; -} - void runtime·memcopy8(uintptr s, void *a, void *b) { @@ -87,13 +61,6 @@ runtime·memcopy8(uintptr s, void *a, void *b) *(uint8*)a = *(uint8*)b; } -void -runtime·memequal16(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(uint16*)a == *(uint16*)b; -} - void runtime·memcopy16(uintptr s, void *a, void *b) { @@ -105,13 +72,6 @@ runtime·memcopy16(uintptr s, void *a, void *b) *(uint16*)a = *(uint16*)b; } -void -runtime·memequal32(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(uint32*)a == *(uint32*)b; -} - void runtime·memcopy32(uintptr s, void *a, void *b) { @@ -123,13 +83,6 @@ runtime·memcopy32(uintptr s, void *a, void *b) *(uint32*)a = *(uint32*)b; } -void -runtime·memequal64(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(uint64*)a == *(uint64*)b; -} - void runtime·memcopy64(uintptr s, void *a, void *b) { @@ -141,13 +94,6 @@ runtime·memcopy64(uintptr s, void *a, void *b) *(uint64*)a = *(uint64*)b; } -void -runtime·memequal128(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = ((uint64*)a)[0] == ((uint64*)b)[0] && ((uint64*)a)[1] == ((uint64*)b)[1]; -} - void runtime·memcopy128(uintptr s, void *a, void *b) { @@ -161,42 +107,6 @@ runtime·memcopy128(uintptr s, void *a, void *b) ((uint64*)a)[1] = ((uint64*)b)[1]; } -void -runtime·f32equal(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(float32*)a == *(float32*)b; -} - -void -runtime·f64equal(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = *(float64*)a == *(float64*)b; -} - -void -runtime·c64equal(bool *eq, uintptr s, void *a, void *b) -{ - Complex64 *ca, *cb; - - USED(s); - ca = a; - cb = b; - *eq = ca->real == cb->real && ca->imag == cb->imag; -} - -void -runtime·c128equal(bool *eq, uintptr s, void *a, void *b) -{ - Complex128 *ca, *cb; - - USED(s); - ca = a; - cb = b; - *eq = ca->real == cb->real && ca->imag == cb->imag; -} - void runtime·algslicecopy(uintptr s, void *a, void *b) { @@ -212,27 +122,6 @@ runtime·algslicecopy(uintptr s, void *a, void *b) ((Slice*)a)->cap = ((Slice*)b)->cap; } -void -runtime·strequal(bool *eq, uintptr s, void *a, void *b) -{ - intgo alen; - byte *s1, *s2; - - USED(s); - alen = ((String*)a)->len; - if(alen != ((String*)b)->len) { - *eq = false; - return; - } - s1 = ((String*)a)->str; - s2 = ((String*)b)->str; - if(s1 == s2) { - *eq = true; - return; - } - *eq = runtime·memeq(s1, s2, alen); -} - void runtime·strprint(uintptr s, void *a) { @@ -260,13 +149,6 @@ runtime·interprint(uintptr s, void *a) runtime·printiface_c(*(Iface*)a); } -void -runtime·interequal(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = runtime·ifaceeq_c(*(Iface*)a, *(Iface*)b); -} - void runtime·intercopy(uintptr s, void *a, void *b) { @@ -287,13 +169,6 @@ runtime·nilinterprint(uintptr s, void *a) runtime·printeface_c(*(Eface*)a); } -void -runtime·nilinterequal(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - *eq = runtime·efaceeq_c(*(Eface*)a, *(Eface*)b); -} - void runtime·nilintercopy(uintptr s, void *a, void *b) { @@ -310,16 +185,6 @@ runtime·nilintercopy(uintptr s, void *a, void *b) extern uintptr runtime·nohashcode; extern uintptr runtime·noequalcode; -void -runtime·noequal(bool *eq, uintptr s, void *a, void *b) -{ - USED(s); - USED(a); - USED(b); - USED(eq); - runtime·panicstring("comparing uncomparable types"); -} - static FuncVal memhashfunc = {(void*)runtime·memhash}; static FuncVal nohashfunc = {(void*)runtime·nohash}; static FuncVal strhashfunc = {(void*)runtime·strhash}; @@ -335,31 +200,48 @@ static FuncVal aeshash32func = {(void*)runtime·aeshash32}; static FuncVal aeshash64func = {(void*)runtime·aeshash64}; static FuncVal aeshashstrfunc = {(void*)runtime·aeshashstr}; +static FuncVal memequalfunc = {(void*)runtime·memequal}; +static FuncVal noequalfunc = {(void*)runtime·noequal}; +static FuncVal strequalfunc = {(void*)runtime·strequal}; +static FuncVal interequalfunc = {(void*)runtime·interequal}; +static FuncVal nilinterequalfunc = {(void*)runtime·nilinterequal}; +static FuncVal f32equalfunc = {(void*)runtime·f32equal}; +static FuncVal f64equalfunc = {(void*)runtime·f64equal}; +static FuncVal c64equalfunc = {(void*)runtime·c64equal}; +static FuncVal c128equalfunc = {(void*)runtime·c128equal}; +static FuncVal memequal0func = {(void*)runtime·memequal0}; +static FuncVal memequal8func = {(void*)runtime·memequal8}; +static FuncVal memequal16func = {(void*)runtime·memequal16}; +static FuncVal memequal32func = {(void*)runtime·memequal32}; +static FuncVal memequal64func = {(void*)runtime·memequal64}; +static FuncVal memequal128func = {(void*)runtime·memequal128}; + + Alg runtime·algarray[] = { -[AMEM] { &memhashfunc, runtime·memequal, runtime·memprint, runtime·memcopy }, -[ANOEQ] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy }, -[ASTRING] { &strhashfunc, runtime·strequal, runtime·strprint, runtime·strcopy }, -[AINTER] { &interhashfunc, runtime·interequal, runtime·interprint, runtime·intercopy }, -[ANILINTER] { &nilinterhashfunc, runtime·nilinterequal, runtime·nilinterprint, runtime·nilintercopy }, -[ASLICE] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·algslicecopy }, -[AFLOAT32] { &f32hashfunc, runtime·f32equal, runtime·memprint, runtime·memcopy }, -[AFLOAT64] { &f64hashfunc, runtime·f64equal, runtime·memprint, runtime·memcopy }, -[ACPLX64] { &c64hashfunc, runtime·c64equal, runtime·memprint, runtime·memcopy }, -[ACPLX128] { &c128hashfunc, runtime·c128equal, runtime·memprint, runtime·memcopy }, -[AMEM0] { &memhashfunc, runtime·memequal0, runtime·memprint, runtime·memcopy0 }, -[AMEM8] { &memhashfunc, runtime·memequal8, runtime·memprint, runtime·memcopy8 }, -[AMEM16] { &memhashfunc, runtime·memequal16, runtime·memprint, runtime·memcopy16 }, -[AMEM32] { &memhashfunc, runtime·memequal32, runtime·memprint, runtime·memcopy32 }, -[AMEM64] { &memhashfunc, runtime·memequal64, runtime·memprint, runtime·memcopy64 }, -[AMEM128] { &memhashfunc, runtime·memequal128, runtime·memprint, runtime·memcopy128 }, -[ANOEQ0] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy0 }, -[ANOEQ8] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy8 }, -[ANOEQ16] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy16 }, -[ANOEQ32] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy32 }, -[ANOEQ64] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy64 }, -[ANOEQ128] { &nohashfunc, runtime·noequal, runtime·memprint, runtime·memcopy128 }, +[AMEM] { &memhashfunc, &memequalfunc, runtime·memprint, runtime·memcopy }, +[ANOEQ] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy }, +[ASTRING] { &strhashfunc, &strequalfunc, runtime·strprint, runtime·strcopy }, +[AINTER] { &interhashfunc, &interequalfunc, runtime·interprint, runtime·intercopy }, +[ANILINTER] { &nilinterhashfunc, &nilinterequalfunc, runtime·nilinterprint, runtime·nilintercopy }, +[ASLICE] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·algslicecopy }, +[AFLOAT32] { &f32hashfunc, &f32equalfunc, runtime·memprint, runtime·memcopy }, +[AFLOAT64] { &f64hashfunc, &f64equalfunc, runtime·memprint, runtime·memcopy }, +[ACPLX64] { &c64hashfunc, &c64equalfunc, runtime·memprint, runtime·memcopy }, +[ACPLX128] { &c128hashfunc, &c128equalfunc, runtime·memprint, runtime·memcopy }, +[AMEM0] { &memhashfunc, &memequal0func, runtime·memprint, runtime·memcopy0 }, +[AMEM8] { &memhashfunc, &memequal8func, runtime·memprint, runtime·memcopy8 }, +[AMEM16] { &memhashfunc, &memequal16func, runtime·memprint, runtime·memcopy16 }, +[AMEM32] { &memhashfunc, &memequal32func, runtime·memprint, runtime·memcopy32 }, +[AMEM64] { &memhashfunc, &memequal64func, runtime·memprint, runtime·memcopy64 }, +[AMEM128] { &memhashfunc, &memequal128func, runtime·memprint, runtime·memcopy128 }, +[ANOEQ0] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy0 }, +[ANOEQ8] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy8 }, +[ANOEQ16] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy16 }, +[ANOEQ32] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy32 }, +[ANOEQ64] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy64 }, +[ANOEQ128] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy128 }, }; // Runtime helpers. @@ -406,20 +288,6 @@ runtime·hashinit(void) } } -// func equal(t *Type, x T, y T) (ret bool) -#pragma textflag NOSPLIT -void -runtime·equal(Type *t, ...) -{ - byte *x, *y; - bool *ret; - - x = (byte*)ROUND((uintptr)(&t+1), t->align); - y = x + t->size; - ret = (bool*)ROUND((uintptr)(y+t->size), Structrnd); - t->alg->equal(ret, t->size, x, y); -} - // Testing adapter for memclr func memclrBytes(s Slice) { runtime·memclr(s.array, s.len); diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s index d2c6e30469..0607bc8021 100644 --- a/src/pkg/runtime/asm_386.s +++ b/src/pkg/runtime/asm_386.s @@ -1149,13 +1149,7 @@ DATA shifts<>+0xfc(SB)/4, $0xff0f0e0d GLOBL shifts<>(SB),RODATA,$256 -TEXT runtime·memeq(SB),NOSPLIT,$0-12 - MOVL a+0(FP), SI - MOVL b+4(FP), DI - MOVL count+8(FP), BX - JMP runtime·memeqbody(SB) - -TEXT runtime·gomemeq(SB),NOSPLIT,$0-13 +TEXT runtime·memeq(SB),NOSPLIT,$0-13 MOVL a+0(FP), SI MOVL b+4(FP), DI MOVL size+8(FP), BX @@ -2266,38 +2260,3 @@ TEXT runtime·fastrand2(SB), NOSPLIT, $0-4 MOVL DX, m_fastrand(AX) MOVL DX, ret+0(FP) RET - -// The goeq trampoline is necessary while we have -// both Go and C calls to alg functions. Once we move all call -// sites to Go, we can redo the eq functions to use the -// Go calling convention and remove this. - -// convert call to: -// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool -// to: -// func (eq *bool, size uintptr, p, q unsafe.Pointer) -TEXT runtime·goeq(SB), NOSPLIT, $16-17 - FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB) - FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB) - MOVL alg+0(FP), AX - MOVL alg_equal(AX), AX - MOVL p+4(FP), CX - MOVL q+8(FP), DX - MOVL size+12(FP), DI - LEAL ret+16(FP), SI - MOVL SI, 0(SP) - MOVL DI, 4(SP) - MOVL CX, 8(SP) - MOVL DX, 12(SP) - PCDATA $PCDATA_StackMapIndex, $0 - CALL *AX - RET - -DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args -DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4)) -GLOBL gcargs_goeq<>(SB),RODATA,$12 - -DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals -GLOBL gclocals_goeq<>(SB),RODATA,$8 diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s index 19e9f1d3a2..0fd21d1795 100644 --- a/src/pkg/runtime/asm_amd64.s +++ b/src/pkg/runtime/asm_amd64.s @@ -1117,13 +1117,7 @@ DATA shifts<>+0xf0(SB)/8, $0x0807060504030201 DATA shifts<>+0xf8(SB)/8, $0xff0f0e0d0c0b0a09 GLOBL shifts<>(SB),RODATA,$256 -TEXT runtime·memeq(SB),NOSPLIT,$0-24 - MOVQ a+0(FP), SI - MOVQ b+8(FP), DI - MOVQ count+16(FP), BX - JMP runtime·memeqbody(SB) - -TEXT runtime·gomemeq(SB),NOSPLIT,$0-25 +TEXT runtime·memeq(SB),NOSPLIT,$0-25 MOVQ a+0(FP), SI MOVQ b+8(FP), DI MOVQ size+16(FP), BX @@ -2305,38 +2299,3 @@ TEXT runtime·fastrand2(SB), NOSPLIT, $0-4 MOVL DX, m_fastrand(AX) MOVL DX, ret+0(FP) RET - -// goeq trampoline is necessary while we have -// both Go and C calls to alg functions. Once we move all call -// sites to Go, we can redo the eq function to use the -// Go calling convention and remove this. - -// convert call to: -// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool -// to: -// func (eq *bool, size uintptr, p, q unsafe.Pointer) -TEXT runtime·goeq(SB), NOSPLIT, $32-33 - FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB) - FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB) - MOVQ alg+0(FP), AX - MOVQ alg_equal(AX), AX - MOVQ p+8(FP), CX - MOVQ q+16(FP), DX - MOVQ size+24(FP), DI - LEAQ ret+32(FP), SI - MOVQ SI, 0(SP) - MOVQ DI, 8(SP) - MOVQ CX, 16(SP) - MOVQ DX, 24(SP) - PCDATA $PCDATA_StackMapIndex, $0 - CALL *AX - RET - -DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args -DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4)) -GLOBL gcargs_goeq<>(SB),RODATA,$12 - -DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals -GLOBL gclocals_goeq<>(SB),RODATA,$8 diff --git a/src/pkg/runtime/asm_amd64p32.s b/src/pkg/runtime/asm_amd64p32.s index f2a1f2a0bc..69e050f90d 100644 --- a/src/pkg/runtime/asm_amd64p32.s +++ b/src/pkg/runtime/asm_amd64p32.s @@ -775,13 +775,7 @@ TEXT runtime·aeshash32(SB),NOSPLIT,$0-24 TEXT runtime·aeshash64(SB),NOSPLIT,$0-24 RET -TEXT runtime·memeq(SB),NOSPLIT,$0-12 - MOVL a+0(FP), SI - MOVL b+4(FP), DI - MOVL count+8(FP), BX - JMP runtime·memeqbody(SB) - -TEXT runtime·gomemeq(SB),NOSPLIT,$0-17 +TEXT runtime·memeq(SB),NOSPLIT,$0-17 MOVL a+0(FP), SI MOVL b+4(FP), DI MOVL size+8(FP), BX @@ -1180,38 +1174,3 @@ TEXT runtime·fastrand2(SB), NOSPLIT, $0-4 MOVL DX, m_fastrand(AX) MOVL DX, ret+0(FP) RET - -// The goeq trampoline is necessary while we have -// both Go and C calls to alg functions. Once we move all call -// sites to Go, we can redo the eq functions to use the -// Go calling convention and remove this. - -// convert call to: -// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool -// to: -// func (eq *bool, size uintptr, p, q unsafe.Pointer) -TEXT runtime·goeq(SB), NOSPLIT, $16-17 - FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB) - FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB) - MOVL alg+0(FP), AX - MOVL alg_equal(AX), AX - MOVL p+4(FP), CX - MOVL q+8(FP), DX - MOVL size+12(FP), DI - LEAL ret+16(FP), SI - MOVL SI, 0(SP) - MOVL DI, 4(SP) - MOVL CX, 8(SP) - MOVL DX, 12(SP) - PCDATA $PCDATA_StackMapIndex, $0 - CALL *AX - RET - -DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args -DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4)) -GLOBL gcargs_goeq<>(SB),RODATA,$12 - -DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals -GLOBL gclocals_goeq<>(SB),RODATA,$8 diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s index 406a426078..324b27b18f 100644 --- a/src/pkg/runtime/asm_arm.s +++ b/src/pkg/runtime/asm_arm.s @@ -703,24 +703,7 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0 MOVW $0, R0 MOVW (R0), R1 -TEXT runtime·memeq(SB),NOSPLIT,$-4-12 - MOVW a+0(FP), R1 - MOVW b+4(FP), R2 - MOVW n+8(FP), R3 - ADD R1, R3, R6 - MOVW $1, R0 -_next: - CMP R1, R6 - RET.EQ - MOVBU.P 1(R1), R4 - MOVBU.P 1(R2), R5 - CMP R4, R5 - BEQ _next - - MOVW $0, R0 - RET - -TEXT runtime·gomemeq(SB),NOSPLIT,$-4-13 +TEXT runtime·memeq(SB),NOSPLIT,$-4-13 MOVW a+0(FP), R1 MOVW b+4(FP), R2 MOVW size+8(FP), R3 @@ -1268,38 +1251,3 @@ TEXT runtime·fastrand2(SB), NOSPLIT, $-4-4 MOVW R0, m_fastrand(R1) MOVW R0, ret+0(FP) RET - -// The goeq trampoline is necessary while we have -// both Go and C calls to alg functions. Once we move all call -// sites to Go, we can redo the eq functions to use the -// Go calling convention and remove this. - -// convert call to: -// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool -// to: -// func (eq *bool, size uintptr, p, q unsafe.Pointer) -TEXT runtime·goeq(SB), NOSPLIT, $16-17 - FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB) - FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB) - MOVW alg+0(FP), R0 - MOVW alg_equal(R0), R0 - MOVW p+4(FP), R1 - MOVW q+8(FP), R2 - MOVW size+12(FP), R3 - ADD $40, R13, R4 - MOVW R4, 4(R13) - MOVW R3, 8(R13) - MOVW R2, 12(R13) - MOVW R1, 16(R13) - PCDATA $PCDATA_StackMapIndex, $0 - BL (R0) - RET - -DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args -DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4)) -GLOBL gcargs_goeq<>(SB),RODATA,$12 - -DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap -DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals -GLOBL gclocals_goeq<>(SB),RODATA,$8 diff --git a/src/pkg/runtime/hashmap.go b/src/pkg/runtime/hashmap.go index 6706290974..9dcf48242f 100644 --- a/src/pkg/runtime/hashmap.go +++ b/src/pkg/runtime/hashmap.go @@ -243,7 +243,8 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if h == nil || h.count == 0 { return unsafe.Pointer(t.elem.zero) } - hash := goalg(t.key.alg).hash(key, uintptr(t.key.size), uintptr(h.hash0)) + alg := goalg(t.key.alg) + hash := alg.hash(key, uintptr(t.key.size), uintptr(h.hash0)) m := uintptr(1)<data = e.data; return true; } - -static bool -ifaceeq1(void *data1, void *data2, Type *t) -{ - uintptr size; - Alg *alg; - Eface err; - bool eq; - - alg = t->alg; - size = t->size; - - if(alg->equal == runtime·noequal) { - // calling noequal will panic too, - // but we can print a better error. - runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err); - runtime·panic(err); - } - - eq = 0; - if(size <= sizeof(data1)) - alg->equal(&eq, size, &data1, &data2); - else - alg->equal(&eq, size, data1, data2); - return eq; -} - -bool -runtime·ifaceeq_c(Iface i1, Iface i2) -{ - if(i1.tab != i2.tab) - return false; - if(i1.tab == nil) - return true; - return ifaceeq1(i1.data, i2.data, i1.tab->type); -} - -bool -runtime·efaceeq_c(Eface e1, Eface e2) -{ - if(e1.type != e2.type) - return false; - if(e1.type == nil) - return true; - return ifaceeq1(e1.data, e2.data, e1.type); -} diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index b85198f480..62100a783a 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -634,7 +634,7 @@ typedef struct Alg Alg; struct Alg { FuncVal* hash; - void (*equal)(bool*, uintptr, void*, void*); + FuncVal* equal; void (*print)(uintptr, void*); void (*copy)(uintptr, void*, void*); }; @@ -665,13 +665,21 @@ void runtime·aeshash32(void*, uintptr, uintptr, uintptr); void runtime·aeshash64(void*, uintptr, uintptr, uintptr); void runtime·aeshashstr(void*, uintptr, uintptr, uintptr); -void runtime·memequal(bool*, uintptr, void*, void*); -void runtime·noequal(bool*, uintptr, void*, void*); -void runtime·strequal(bool*, uintptr, void*, void*); -void runtime·interequal(bool*, uintptr, void*, void*); -void runtime·nilinterequal(bool*, uintptr, void*, void*); - -bool runtime·memeq(void*, void*, uintptr); +void runtime·memequal(void*, void*, uintptr, bool); +void runtime·noequal(void*, void*, uintptr, bool); +void runtime·strequal(void*, void*, uintptr, bool); +void runtime·interequal(void*, void*, uintptr, bool); +void runtime·nilinterequal(void*, void*, uintptr, bool); +void runtime·f32equal(void*, void*, uintptr, bool); +void runtime·f64equal(void*, void*, uintptr, bool); +void runtime·c64equal(void*, void*, uintptr, bool); +void runtime·c128equal(void*, void*, uintptr, bool); +void runtime·memequal0(void*, void*, uintptr, bool); +void runtime·memequal8(void*, void*, uintptr, bool); +void runtime·memequal16(void*, void*, uintptr, bool); +void runtime·memequal32(void*, void*, uintptr, bool); +void runtime·memequal64(void*, void*, uintptr, bool); +void runtime·memequal128(void*, void*, uintptr, bool); void runtime·memprint(uintptr, void*); void runtime·strprint(uintptr, void*); @@ -873,8 +881,6 @@ MCache* runtime·allocmcache(void); void runtime·freemcache(MCache*); void runtime·mallocinit(void); void runtime·chaninit(void); -bool runtime·ifaceeq_c(Iface, Iface); -bool runtime·efaceeq_c(Eface, Eface); void* runtime·mallocgc(uintptr size, Type* typ, uint32 flag); void runtime·runpanic(Panic*); uintptr runtime·getcallersp(void*); diff --git a/src/pkg/runtime/stubs.go b/src/pkg/runtime/stubs.go index 77eece9433..9c18434d5d 100644 --- a/src/pkg/runtime/stubs.go +++ b/src/pkg/runtime/stubs.go @@ -111,20 +111,12 @@ func starttheworld() func stoptheworld() func clearpools() -// in asm_*.s -//go:noescape -func gohash(a *alg, p unsafe.Pointer, size uintptr, seed uintptr) uintptr - -// in asm_*.s -//go:noescape -func goeq(alg *alg, p, q unsafe.Pointer, size uintptr) bool - // exported value for testing var hashLoad = loadFactor // in asm_*.s //go:noescape -func gomemeq(a, b unsafe.Pointer, size uintptr) bool +func memeq(a, b unsafe.Pointer, size uintptr) bool // Code pointers for the nohash/noequal algorithms. Used for producing better error messages. var nohashcode uintptr @@ -147,6 +139,9 @@ type goalgtype struct { // function for hashing objects of this type // (ptr to object, size, seed) -> hash hash func(unsafe.Pointer, uintptr, uintptr) uintptr + // function for comparing objects of this type + // (ptr to object A, ptr to object B, size) -> ==? + equal func(unsafe.Pointer, unsafe.Pointer, uintptr) bool } func goalg(a *alg) *goalgtype { -- cgit v1.3-5-g9baa