Skip to content

cmd/compile: support inlining OCALLPART #18493

@josharian

Description

@josharian

context.WithCancel allocates three objects. One is a *cancelCtx, unavoidable. Another is a chan struct{}, hard to eliminate without runtime magic or a language change. The last is a closure:

	return &c, func() { c.cancel(true, Canceled) }

Canceled is a top-level var initialized with errors.New; it is an *errorString under the hood. Note that true and Canceled are both static data. And c has already leaked to the heap, courtesy of the &c return. The method cancel can be staticly resolved. So it seems like in principle it ought to be possible not to allocate for the closure; everything we need is either static or on the heap already.

Here's a straw man for how this might be accomplished. Generate a wrapper method:

func (c * cancelCtx) cancelTrueCanceled() { c.cancel(true, Canceled) }

and rewrite the original return to:

	return &c, c.cancelTrueCanceled

(This can also be done manually, if this first transformation is too hard.) Now we have a partial method call with no free variables instead of a closure.

Now represent this partial method call as a tuple: <receiver, method>. The receiver we already have. The method could be a function pointer. The receiver and function pointers are values and can be passed around safely on the stack. This is not dissimilar to what we do now, except that the existing formulation always requires heap allocation. In some (but not all) cases, the heap allocation could be avoided.

This is might be too big a change relative to the benefits it would bring, but thought I'd record it anyway. And maybe someone else sees a simpler way to eliminate this allocation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions