From 05b4591414e6e3ba182c31a743037daa4c096023 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:50:20 +1100 Subject: [PATCH 1/3] buffer: split runtime.s into pre- and post-Go 1.8 files. Go 1.8 renamed this function; cf. golang/go@87e48c5. --- internal/buffer/runtime.go | 2 + internal/buffer/runtime_go1.8.s | 37 +++++++++++++++++++ .../buffer/{runtime.s => runtime_other.s} | 1 + 3 files changed, 40 insertions(+) create mode 100644 internal/buffer/runtime_go1.8.s rename internal/buffer/{runtime.s => runtime_other.s} (98%) diff --git a/internal/buffer/runtime.go b/internal/buffer/runtime.go index 672c8a1..c0806fb 100644 --- a/internal/buffer/runtime.go +++ b/internal/buffer/runtime.go @@ -19,6 +19,8 @@ import "unsafe" //go:noescape // Zero the n bytes starting at p. +// +// REQUIRES: the region does not contain any Go pointers. func memclr(p unsafe.Pointer, n uintptr) //go:noescape diff --git a/internal/buffer/runtime_go1.8.s b/internal/buffer/runtime_go1.8.s new file mode 100644 index 0000000..201a511 --- /dev/null +++ b/internal/buffer/runtime_go1.8.s @@ -0,0 +1,37 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build amd64 arm64 ppc64 ppc64le +// +build go1.8 + +// Assembly code isn't subject to visibility restrictions, so we can jump +// directly into package runtime. +// +// Technique copied from here: +// https://github.com/golang/go/blob/d8c6dac/src/os/signal/sig.s + +#include "textflag.h" + +#ifdef GOARCH_ppc64 +#define JMP BR +#endif +#ifdef GOARCH_ppc64le +#define JMP BR +#endif + +TEXT ·memclr(SB),NOSPLIT,$0-16 + JMP runtime·memclrNoHeapPointers(SB) + +TEXT ·memmove(SB),NOSPLIT,$0-24 + JMP runtime·memmove(SB) diff --git a/internal/buffer/runtime.s b/internal/buffer/runtime_other.s similarity index 98% rename from internal/buffer/runtime.s rename to internal/buffer/runtime_other.s index f39415a..139cc65 100644 --- a/internal/buffer/runtime.s +++ b/internal/buffer/runtime_other.s @@ -13,6 +13,7 @@ // limitations under the License. // +build amd64 arm64 ppc64 ppc64le +// +build !go1.8 // Assembly code isn't subject to visibility restrictions, so we can jump // directly into package runtime. From bd496ea0480b848cf655670677b30f2e27702fe4 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 13:58:09 +1100 Subject: [PATCH 2/3] buffer: don't use memclr for the tiny header, whose size is known. --- internal/buffer/out_message.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index bd46ae2..8166b6f 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -56,7 +56,7 @@ func init() { // are solely a zeroed fusekernel.OutHeader struct. func (m *OutMessage) Reset() { m.payloadOffset = 0 - memclr(unsafe.Pointer(&m.header), uintptr(OutMessageHeaderSize)) + m.header = fusekernel.OutHeader{} } // OutHeader returns a pointer to the header at the start of the message. From cea04881bd376b3681655f0976654016255c542a Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 19 Dec 2016 14:41:59 +1100 Subject: [PATCH 3/3] buffer: generate decent code for OutMessage.Reset in Go 1.8 beta 2. --- internal/buffer/out_message.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/internal/buffer/out_message.go b/internal/buffer/out_message.go index 8166b6f..94d5407 100644 --- a/internal/buffer/out_message.go +++ b/internal/buffer/out_message.go @@ -55,8 +55,22 @@ func init() { // Reset resets m so that it's ready to be used again. Afterward, the contents // are solely a zeroed fusekernel.OutHeader struct. func (m *OutMessage) Reset() { - m.payloadOffset = 0 - m.header = fusekernel.OutHeader{} + // Ideally we'd like to write: + // + // m.payloadOffset = 0 + // m.header = fusekernel.OutHeader{} + // + // But Go 1.8 beta 2 generates bad code for this + // (https://golang.org/issue/18370). Encourage it to generate the same code + // as Go 1.7.4 did. + if unsafe.Offsetof(m.payload) != 24 { + panic("unexpected OutMessage layout") + } + + a := (*[3]uint64)(unsafe.Pointer(m)) + a[0] = 0 + a[1] = 0 + a[2] = 0 } // OutHeader returns a pointer to the header at the start of the message.