preface

From the previous part of block, we already know the three representations of block and the understanding of reference counting and circular reference. Through this article, we will further understand its underlying implementation, what is the structure inside? How to copy, how to capture, save and release?

CPP file analysis

Block generates the corresponding member variable and assigns the value to the internal member variable if an external variable comes in.

No member variables

Remove the strong type after the code, the first step function declaration, the second step, function call save. That is, if the function is not called, it is not saved.

Looking at the actual function implementation, you can see that the block at compile time isStack block, and I’m accessing external variables without weak references, should beHeap blockThat’s right. I guess it wasrunPhase is treated.

If you want to make changes to external variables, add__blockOtherwise, the internally generated variable A is not the same address as the external variable A. Then add the__blockWhat does it do?

It generates an A of type__Block_byref_a_0

__Block_byref_a_0It’s a structure.

The address of the structure itself is used in the function declaration.

So when you modify a value, you’re modifying its own value, you’re modifying the same memory space.

Source code analysis

Find the source code project

By breaking points.

The source code can be found in libclosure-79, but it is not open source.

findblock_copyIf it is a free state or if it is global, it is directly returned to the block. If it is a stack block, it is requiredcopyA copy, because in the compiler to open up space operations, will increase the compiler’s burden. Then allcopyA copy, ISA points to becomeHeap block.

Take a look at the block_layout structure and take a look at the main parameter representations

isaPoint to, is it a stack block or a heap block or a global block.flagsidentifierinvokeA function call

Why do stack blocks become heap blocks?

You saw earlier that it was a heap block and it came in as a stack block at compile time, so what did I do? Take a look at the print before and after copy through the register.

v8@? 0 can be meant by printing the signature [NSMethodSignature signatureWithObjCTypes:”v8@?0″].

Number of arguments Current parameter 1, return null.

Object of type FlagsBlock

Memory8 bytes.

Why sign?

When invoke is invoked, it is also a message sending mechanism, which is the same as message forwarding before. The last step is also signature, which is required when the method takes effect or is abnormal.

Block_descriptor

So let’s look at the normal situation if we use external variables. Copy and dispose, which are recorded in Block_descriptor1, are displayed differently, depending on the case, to obtain Block_descriptor2 or Block_descriptor3 by memory translation. Because the memory here is contiguous, it can be shifted.

An addition to the __block pointer copy

If only ordinary objects come in, the internally generated member variable is not the same as the external captured member variable, even though they point to the same space and have the same value. If the object is __block decorated and meets BLOCK_BYREF_HAS_COPY_DISPOSE, that is to capture the external variable, open up the heap memory and copy, after getting the variable, byref_keep holds the whole life cycle of the variable to prevent the variable from being released. The entire block is also released.

   **struct** Block_byref_2 {

    // requires BLOCK_BYREF_HAS_COPY_DISPOSE

    BlockByrefKeepFunction byref_keep; //= __Block_byref_id_object_copy_131

    BlockByrefDestroyFunction byref_destroy; // = __Block_byref_id_object_dispose_131

};
Copy the code

Block The process of capturing external variables.

There are three main ways to analyze captured variables.

The first type is object, which is a direct pointer to the object, the second type is block, which is the capture of its own block, and the third type is byref.

Official notes.

If the variable is a __block modifier and is captured, the corresponding __Block_byref_id_object_copy method (layer 2 copy) is generated in addition to the normal stack to heap copy of the block. The _Block_object_assign method is copied (layer 3 copy) in this method.

The internal structure of the Block is defined

Members of the Block_layout structure have the following meanings:

  • Isa: a pointer to the owning class, which is the type of the block

  • Flags: Flags variable used to implement internal operations of blocks

  • Reserved: Reserved variables

  • Invoke: A pointer to a function that is invoked when a block is executed

  • Descriptor: Detailed description of blocks, including the copy/dispose function, used when a block references external variables

  • Variables: variables outside the block scope that do not exist if the block does not call any external variables

The members of the Block_descriptor structure have the following meanings:

  • Reserved: Reserved variables
  • Size: indicates the memory size of a block
  • Copy: copies the block data__blockModify the external variable
  • And the dispose:copyMethod to configure an application to release resources

A variable decorated with __block is encapsulated as an object. The __Block_byref_a_0 member has the following meanings:

  • __isa: a pointer to the owning class
  • __forwarding: Refers to the copy of an object in the heap
  • __flags: Flags that are used to implement internal operations on blocks
  • __size: The memory size of the object
  • A: Primitive type of variable