Contents
  1. 1. Block 的类型

https://clang.llvm.org/docs/Block-ABI-Apple.html llvm 对 flags 文档的描述不完整,最新的代码已经扩展到了 1 << 31

enum {
    // Set to true on blocks that have captures (and thus are not true
    // global blocks) but are known not to escape for various other
    // reasons. For backward compatiblity with old runtimes, whenever
    // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
    // non-escaping block returns the original block and releasing such a
    // block is a no-op, which is exactly how global blocks are handled.
    BLOCK_IS_NOESCAPE      =  (1 << 23),

    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
    BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code
    BLOCK_IS_GLOBAL =         (1 << 28),
    BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE
    BLOCK_HAS_SIGNATURE =     (1 << 30),
};

翻看 block 的实现可以看到

// Values for Block_layout->flags to describe block objects
enum {
    BLOCK_DEALLOCATING =      (0x0001),  // runtime
    BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
    BLOCK_NEEDS_FREE =        (1 << 24), // runtime
    BLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
    BLOCK_HAS_CTOR =          (1 << 26), // compiler: helpers have C++ code
    BLOCK_IS_GC =             (1 << 27), // runtime
    BLOCK_IS_GLOBAL =         (1 << 28), // compiler
    BLOCK_USE_STRET =         (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
    BLOCK_HAS_SIGNATURE  =    (1 << 30), // compiler
    BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31)  // compiler
};

代码随处可见的下列汇编就是将 (1<<29)|(1<<30) 赋值
MOV W8, #0xC2000000

Block 的类型

众所周知有 global、stack、malloc 类型,查看源代码发现不止这三个

Foundation 会在合适的时机把这些变量填充为正确的值

void * _NSConcreteStackBlock[32] = { 0 };
void * _NSConcreteMallocBlock[32] = { 0 };
void * _NSConcreteAutoBlock[32] = { 0 };
void * _NSConcreteFinalizingBlock[32] = { 0 };
void * _NSConcreteGlobalBlock[32] = { 0 };
void * _NSConcreteWeakBlockVariable[32] = { 0 };

global 只要不截获自动变量,都是 global 的
(一)static

static Block block = ^(int a) {
    return 0;
}; 这是 global



int i = 0;
static Block block = ^(int a) {
    return i;
}; 这是编译不过

(二)文件级别,就是全局的

block = ^(int a) {
  return 0;
}; 这是 global

int i = 0;
block = ^(int a) {
  return i;
}; 这是 malloc 的

__weak Block block;
int i = 0;
block = ^(int a) {
  return i;
}; 这是 stack 的

所以只要是被 __weak 修饰的都是 stack 的。

malloc 只要是截获了自动变量的,都是的 malloc 的。

malloc 的情况下,只要给加一个 __weak 修饰,就是 stack 的。

Contents
  1. 1. Block 的类型