deref = true
res = res.Args[0]
}
- s.assign(n.List.First(), res, needwritebarrier(n.List.First(), n.Rlist.First()), deref, 0, false)
+ s.assign(n.List.First(), res, needwritebarrier(n.List.First()), deref, 0, false)
s.assign(n.List.Second(), resok, false, false, 0, false)
return
v := s.intrinsicCall(n.Rlist.First())
v1 := s.newValue1(ssa.OpSelect0, n.List.First().Type, v)
v2 := s.newValue1(ssa.OpSelect1, n.List.Second().Type, v)
- // Make a fake node to mimic loading return value, ONLY for write barrier test.
- // This is future-proofing against non-scalar 2-result intrinsics.
- // Currently we only have scalar ones, which result in no write barrier.
- fakeret := &Node{Op: OINDREGSP}
- s.assign(n.List.First(), v1, needwritebarrier(n.List.First(), fakeret), false, 0, false)
- s.assign(n.List.Second(), v2, needwritebarrier(n.List.Second(), fakeret), false, 0, false)
+ s.assign(n.List.First(), v1, needwritebarrier(n.List.First()), false, 0, false)
+ s.assign(n.List.Second(), v2, needwritebarrier(n.List.Second()), false, 0, false)
return
case ODCL:
}
var r *ssa.Value
var isVolatile bool
- needwb := n.Right != nil && needwritebarrier(n.Left, n.Right)
+ needwb := n.Right != nil && needwritebarrier(n.Left)
deref := !canSSAType(t)
if deref {
if rhs == nil {
r = s.expr(rhs)
}
}
- if rhs != nil && rhs.Op == OAPPEND && needwritebarrier(n.Left, rhs) {
+ if rhs != nil && rhs.Op == OAPPEND && needwritebarrier(n.Left) {
// The frontend gets rid of the write barrier to enable the special OAPPEND
// handling above, but since this is not a special case, we need it.
// TODO: just add a ptr graying to the end of growslice?
if l.Ullman >= UINF || l.Op == OINDEXMAP {
return true
}
- var r Node
- if needwritebarrier(l, &r) {
+ if needwritebarrier(l) {
return true
}
if eqtype(l.Type, rt) {
return false
}
-// Do we need a write barrier for the assignment l = r?
-func needwritebarrier(l *Node, r *Node) bool {
+// Do we need a write barrier for assigning to l?
+func needwritebarrier(l *Node) bool {
if !use_writebarrier {
return false
}
return false
}
- // Implicit zeroing is still zeroing, so it needs write
- // barriers. In practice, these are all to stack variables
- // (even if isstack isn't smart enough to figure that out), so
- // they'll be eliminated by the backend.
- if r == nil {
- return true
- }
-
- // Ignore no-op conversions when making decision.
- // Ensures that xp = unsafe.Pointer(&x) is treated
- // the same as xp = &x.
- for r.Op == OCONVNOP {
- r = r.Left
- }
-
// TODO: We can eliminate write barriers if we know *both* the
// current and new content of the slot must already be shaded.
// We know a pointer is shaded if it's nil, or points to
// writes to just-allocated objects. Unfortunately, knowing
// the "current" value of the slot requires flow analysis.
- // No write barrier for storing address of stack values,
- // which are guaranteed only to be written to the stack.
- if r.Op == OADDR && isstack(r.Left) {
- return false
- }
-
// Otherwise, be conservative and use write barrier.
return true
}