查看Ruby Under a Microscope的源代码
←
Ruby Under a Microscope
跳转到:
导航
、
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
== 闭包 == * rb_block_struct 和 rb_control_frame_struct 两个结构,闭包本质是代码块和它的上下文环境(EP指针)。rb_block_t 结构体是 rb_control_frame_t 的一部分,避免分配。但是在最新代码里已经修改了, rb_struct 变成一个 union,其中 rb_captured_block 是 rb_control_frame_struct 一部分 : <pre> typedef struct rb_control_frame_struct { const VALUE *pc; /* cfp[0] */ VALUE *sp; /* cfp[1] */ const rb_iseq_t *iseq; /* cfp[2] */ VALUE self; /* cfp[3] / block[0] */ const VALUE *ep; /* cfp[4] / block[1] */ const void *block_code; /* cfp[5] / block[2] */ /* iseq or ifunc */ #if VM_DEBUG_BP_CHECK VALUE *bp_check; /* cfp[6] */ #endif } rb_control_frame_t; enum rb_block_type { block_type_iseq, block_type_ifunc, block_type_symbol, block_type_proc }; struct rb_block { union { struct rb_captured_block captured; VALUE symbol; VALUE proc; } as; enum rb_block_type type; }; typedef struct rb_control_frame_struct { const VALUE *pc; /* cfp[0] */ VALUE *sp; /* cfp[1] */ const rb_iseq_t *iseq; /* cfp[2] */ VALUE self; /* cfp[3] / block[0] */ const VALUE *ep; /* cfp[4] / block[1] */ const void *block_code; /* cfp[5] / block[2] */ /* iseq or ifunc */ #if VM_DEBUG_BP_CHECK VALUE *bp_check; /* cfp[6] */ #endif } rb_control_frame_t; </pre> * 上述代码中比较有意思的是 rb_block_type 分成四种。 * 从测试来看(2.4), each block 确实会比 while 循环慢(在我的机器上是 60%)。因为block 需要做更多的工作:创建栈帧、拷贝 EP 指针等。 * 创建 proc 的时候,会复制一份当前的栈帧副本 rb_env_t,proc 和 lambda 本质上是一样的,通过一个布尔值区分 is_lambda: <pre> typedef struct { const struct rb_block block; int8_t safe_level; /* 0..1 */ int8_t is_from_method; /* bool */ int8_t is_lambda; /* bool */ } rb_proc_t; typedef struct { VALUE flags; /* imemo header */ const rb_iseq_t *iseq; const VALUE *ep; const VALUE *env; unsigned int env_size; } rb_env_t; </pre> * proc 的创建是通过 RTypedData 和 rb_proc_t 结合来创建的: <pre> struct RTypedData { struct RBasic basic; const rb_data_type_t *type; VALUE typed_flag; /* 1 or not */ void *data; }; /* Proc */ VALUE rb_proc_create_from_captured(VALUE klass, const struct rb_captured_block *captured, enum rb_block_type block_type, int8_t safe_level, int8_t is_from_method, int8_t is_lambda) { VALUE procval = rb_proc_alloc(klass); rb_proc_t *proc = RTYPEDDATA_DATA(procval); VM_ASSERT(VM_EP_IN_HEAP_P(GET_THREAD(), captured->ep)); /* copy block */ RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self); RB_OBJ_WRITE(procval, &proc->block.as.captured.code.val, captured->code.val); *((const VALUE **)&proc->block.as.captured.ep) = captured->ep; RB_OBJ_WRITTEN(procval, Qundef, VM_ENV_ENVVAL(captured->ep)); vm_block_type_set(&proc->block, block_type); proc->safe_level = safe_level; proc->is_from_method = is_from_method; proc->is_lambda = is_lambda; return procval; } </pre> tagged struct 也是常见的 c 语言技巧。
返回到
Ruby Under a Microscope
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面