diff options
Diffstat (limited to 'src/cmd/compile/internal/devirtualize/devirtualize.go')
| -rw-r--r-- | src/cmd/compile/internal/devirtualize/devirtualize.go | 90 |
1 files changed, 42 insertions, 48 deletions
diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go index 554e935c3e..6c41d4efd8 100644 --- a/src/cmd/compile/internal/devirtualize/devirtualize.go +++ b/src/cmd/compile/internal/devirtualize/devirtualize.go @@ -57,58 +57,52 @@ func Call(call *ir.CallExpr) { return } - if base.Debug.Unified != 0 { - // N.B., stencil.go converts shape-typed values to interface type - // using OEFACE instead of OCONVIFACE, so devirtualization fails - // above instead. That's why this code is specific to unified IR. - - // If typ is a shape type, then it was a type argument originally - // and we'd need an indirect call through the dictionary anyway. - // We're unable to devirtualize this call. - if typ.IsShape() { - return - } + // If typ is a shape type, then it was a type argument originally + // and we'd need an indirect call through the dictionary anyway. + // We're unable to devirtualize this call. + if typ.IsShape() { + return + } - // If typ *has* a shape type, then it's an shaped, instantiated - // type like T[go.shape.int], and its methods (may) have an extra - // dictionary parameter. We could devirtualize this call if we - // could derive an appropriate dictionary argument. - // - // TODO(mdempsky): If typ has has a promoted non-generic method, - // then that method won't require a dictionary argument. We could - // still devirtualize those calls. - // - // TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It - // should be possible to compute the represented type's runtime - // dictionary from this (e.g., by adding a pointer from T[int]'s - // *runtime._type to .dict.T[int]; or by recognizing static - // references to go:itab.T[int],iface and constructing a direct - // reference to .dict.T[int]). - if typ.HasShape() { - if base.Flag.LowerM != 0 { - base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ) - } - return + // If typ *has* a shape type, then it's an shaped, instantiated + // type like T[go.shape.int], and its methods (may) have an extra + // dictionary parameter. We could devirtualize this call if we + // could derive an appropriate dictionary argument. + // + // TODO(mdempsky): If typ has has a promoted non-generic method, + // then that method won't require a dictionary argument. We could + // still devirtualize those calls. + // + // TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It + // should be possible to compute the represented type's runtime + // dictionary from this (e.g., by adding a pointer from T[int]'s + // *runtime._type to .dict.T[int]; or by recognizing static + // references to go:itab.T[int],iface and constructing a direct + // reference to .dict.T[int]). + if typ.HasShape() { + if base.Flag.LowerM != 0 { + base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ) } + return + } - // Further, if sel.X's type has a shape type, then it's a shaped - // interface type. In this case, the (non-dynamic) TypeAssertExpr - // we construct below would attempt to create an itab - // corresponding to this shaped interface type; but the actual - // itab pointer in the interface value will correspond to the - // original (non-shaped) interface type instead. These are - // functionally equivalent, but they have distinct pointer - // identities, which leads to the type assertion failing. - // - // TODO(mdempsky): We know the type assertion here is safe, so we - // could instead set a flag so that walk skips the itab check. For - // now, punting is easy and safe. - if sel.X.Type().HasShape() { - if base.Flag.LowerM != 0 { - base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type()) - } - return + // Further, if sel.X's type has a shape type, then it's a shaped + // interface type. In this case, the (non-dynamic) TypeAssertExpr + // we construct below would attempt to create an itab + // corresponding to this shaped interface type; but the actual + // itab pointer in the interface value will correspond to the + // original (non-shaped) interface type instead. These are + // functionally equivalent, but they have distinct pointer + // identities, which leads to the type assertion failing. + // + // TODO(mdempsky): We know the type assertion here is safe, so we + // could instead set a flag so that walk skips the itab check. For + // now, punting is easy and safe. + if sel.X.Type().HasShape() { + if base.Flag.LowerM != 0 { + base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type()) } + return } dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil) |
