Original post

Yeah, exactly. So the notion is that at any defer statement – let me describe the current way, before the optimization. The current way is at any defer statement what you do is you kind of create a defer record, and in that record you evaluate all the arguments in the function pointer that you need to defer, and you put that information in the record and you kind of add it to a chain in the runtime, that’s kind of a defer that you’re gonna have to run later. And then all exits you call into the runtime and you run the appropriate defers. So it’s definitely runtime overhead, as you’re adding to the chain in the runtime, and then at the exit you’re chopping into it and run all the defers that are on that big list.

So the optimization is – again, in this case where there are no defers in loops – that we’re gonna generate in-line code at each defer, and at that defer we’re gonna evaluate the arguments in the function pointer, but now we’ll just kind of store it in some stack slots, so basically in some local variable space… And the compiler is gonna keep track of where that data is stored.

The other thing we’re gonna do is we’re gonna store in a bitmask that says “This defer was activated”, so this defer statement was run. That’s the way we deal with conditionals. So as you’re running through the function, you’re storing the defer arguments and the function pointers and you’re storing in that bitmask what defers have run. And then at any exit, we generate again in-line code that says “If this bit is set in the defer bitmask, grab these arguments and this function pointer from the stack slots and run it.” We through in kind of Last In, First Out order, as the defer was defined, to run any of the active defers.

One thing to quickly say though is that this is all at the compiler level that we put in those checks for the defer bits, and stuff… So actually, if there are no conditionals, all the defer bit checks go away, because the compiler knows you set one and then you checked for one, and you set a second bit and you checked for a second bit. So they go away.

You do have to still set the defer bits, because we’re gonna need to know about that stuff for panic and so forth… I can get into more details on that, but in the normal case you’ll store all those arguments, set the defer bits, and then on the exit you’ll run those.