golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.74k stars 17.63k forks source link

cmd/compile: ephemeral slicing doesn't need protection against next object pointers #15397

Open randall77 opened 8 years ago

randall77 commented 8 years ago
func f(b []byte) byte {
    b = b[3:]
    return b[4]
}

We compile this to something like (bounds checks omitted):

    p = b.ptr
    inc = 3
    if b.cap == 3 {
        inc = 0
    }
    p += inc
    return *(p+4)

The if in the middle is there to make sure we don't manufacture a pointer to the next object in memory. But the resulting pointer is never exposed to the garbage collector, so that if is unnecessary. Manufacturing a pointer to the next object in memory is ok if that pointer is never spilled at a safe point. (Bounds checks will make sure such a pointer is never actually used.)

Unfortunately, I don't see an easy way to do this optimization in the current compiler. Marked as unplanned.

See #14849

rasky commented 6 years ago

@randall77 do you happen to have any idea nowadays on how to attack this problem?

josharian commented 6 years ago

I read on some thread somewhere that @aclements is working on “safe points everywhere” which might make this infeasible.

I wonder whether it’d help to concoct a branch-free way to calculate inc.

rasky commented 6 years ago

It's already branch-free, but it's still expensive. With this and the writer barriers, people will always have to remove slicing from performance-critica code, unless we agree on a way forward.

navytux commented 6 years ago

For the reference - the write barrier at b = b[3:] might be maybe omitted: https://github.com/golang/go/issues/24314 (still waiting for @aclements feedback).

randall77 commented 6 years ago

No, I'm still not sure how you would do this. And @josharian is right, if we get safe points everywhere this gets significantly harder.

aclements commented 6 years ago

If you can ensure the out-of-bounds pointer won't be live for more than an instruction or two, it might be okay to mark those as unsafe points. We're absolutely going to need unsafe points for the write barrier, but I've been working on removing them from other compiler constructs (like range loops).