diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index e43da5892b9f..8277092d76b3 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -756,6 +756,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } break; case ZEND_CALLABLE_CONVERT: + case ZEND_DECLARE_LAMBDA_FUNCTION: if (opline->extended_value != (uint32_t)-1) { opline->extended_value = cache_size; cache_size += sizeof(void *); diff --git a/Zend/tests/partial_application/pipe_optimization_004.phpt b/Zend/tests/partial_application/pipe_optimization_004.phpt index 194f08a9c143..2d70493f9d69 100644 --- a/Zend/tests/partial_application/pipe_optimization_004.phpt +++ b/Zend/tests/partial_application/pipe_optimization_004.phpt @@ -70,7 +70,7 @@ $_main: ; (lines=3, args=0, vars=0, tmps=%d) ; (after optimizer) ; %s:1-10 -0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0000 T0 = DECLARE_LAMBDA_FUNCTION %d 0 0001 FREE T0 0002 RETURN int(1) diff --git a/Zend/tests/partial_application/pipe_optimization_007.phpt b/Zend/tests/partial_application/pipe_optimization_007.phpt index be8d773c44ce..03c98e26423c 100644 --- a/Zend/tests/partial_application/pipe_optimization_007.phpt +++ b/Zend/tests/partial_application/pipe_optimization_007.phpt @@ -70,7 +70,7 @@ $_main: ; (lines=3, args=0, vars=0, tmps=%d) ; (after optimizer) ; %s:1-10 -0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0000 T0 = DECLARE_LAMBDA_FUNCTION %d 0 0001 FREE T0 0002 RETURN int(1) diff --git a/Zend/tests/partial_application/pipe_optimization_008.phpt b/Zend/tests/partial_application/pipe_optimization_008.phpt index 96f8d88815ca..baa0f3d8d4ca 100644 --- a/Zend/tests/partial_application/pipe_optimization_008.phpt +++ b/Zend/tests/partial_application/pipe_optimization_008.phpt @@ -66,7 +66,7 @@ $_main: ; (lines=4, args=0, vars=1, tmps=%d) ; (after optimizer) ; %s:1-10 -0000 T1 = DECLARE_LAMBDA_FUNCTION 0 +0000 T1 = DECLARE_LAMBDA_FUNCTION %d 0 0001 BIND_LEXICAL T1 CV0($a) 0002 FREE T1 0003 RETURN int(1) diff --git a/Zend/tests/partial_application/pipe_optimization_013.phpt b/Zend/tests/partial_application/pipe_optimization_013.phpt index 6c2be6728e73..e4fb797657de 100644 --- a/Zend/tests/partial_application/pipe_optimization_013.phpt +++ b/Zend/tests/partial_application/pipe_optimization_013.phpt @@ -54,7 +54,7 @@ $_main: ; (lines=4, args=0, vars=1, tmps=%d) ; (after optimizer) ; %s:1-9 -0000 T1 = DECLARE_LAMBDA_FUNCTION 0 +0000 T1 = DECLARE_LAMBDA_FUNCTION %d 0 0001 BIND_LEXICAL T1 CV0($b) 0002 FREE T1 0003 RETURN int(1) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a2f126fb101d..a34e3a3bd1c0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8942,6 +8942,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, if (op_array->fn_flags & ZEND_ACC_CLOSURE) { opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL); opline->op2.num = func_ref; + opline->extended_value = (uint32_t)-1; } else { opline = get_next_op(); opline->opcode = ZEND_DECLARE_FUNCTION; @@ -9131,6 +9132,23 @@ static zend_op_array *zend_compile_func_decl_ex( zend_compile_stmt(stmt_ast); + if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) { + zend_op_array *declaring_op_array = orig_oparray_context.op_array; + + if ((op_array->fn_flags & ZEND_ACC_STATIC) + && !op_array->static_variables + /* Don't cache closures in main, as those would leak without a proper + * cleanup mechanism. */ + && declaring_op_array->function_name + && declaring_op_array->last) { + zend_op *declare_lambda_op = &declaring_op_array->opcodes[declaring_op_array->last - 1]; + if (declare_lambda_op->opcode == ZEND_DECLARE_LAMBDA_FUNCTION) { + declare_lambda_op->extended_value = declaring_op_array->cache_size; + declaring_op_array->cache_size += sizeof(void *); + } + } + } + if (is_method) { CG(zend_lineno) = decl->start_lineno; zend_check_magic_method_implementation( diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 83ba5e7490cf..cc99a75a6ab9 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -203,6 +203,7 @@ void init_executor(void) /* {{{ */ zend_hash_init(&EG(callable_convert_cache), 8, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&EG(partial_function_application_cache), 8, NULL, zend_partial_op_array_dtor, 0); + zend_stack_init(&EG(lambda_cache), sizeof(zend_object *)); EG(active) = 1; } @@ -268,6 +269,14 @@ void shutdown_destructors(void) /* {{{ */ } /* }}} */ +static void lambda_dtor(zend_object **closure_ptr) +{ + zend_object *closure = *closure_ptr; + if (GC_DELREF(closure) == 0) { + zend_objects_store_del(closure); + } +} + /* Free values held by the executor. */ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) { @@ -421,6 +430,7 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) zend_hash_clean(&EG(callable_convert_cache)); zend_hash_clean(&EG(partial_function_application_cache)); + zend_stack_clean(&EG(lambda_cache), (void (*)(void *)) lambda_dtor, 1); #if ZEND_DEBUG if (!CG(unclean_shutdown)) { diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 83360a2c96d2..4d5e300e2859 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -326,6 +326,7 @@ struct _zend_executor_globals { HashTable callable_convert_cache; HashTable partial_function_application_cache; + zend_stack lambda_cache; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d89d460d9d9d..cf8072646ee4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8409,13 +8409,21 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST) ZEND_VM_NEXT_OPCODE_EX(1, 2); } -ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM) +ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, UNUSED, NUM, NUM|CACHE_SLOT) { USE_OPLINE zend_function *func; zval *object; zend_class_entry *called_scope; + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + ZEND_VM_NEXT_OPCODE(); + } + } + func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; if (Z_TYPE(EX(This)) == IS_OBJECT) { called_scope = Z_OBJCE(EX(This)); @@ -8432,7 +8440,12 @@ ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM) SAVE_OPLINE(); zend_create_closure(EX_VAR(opline->result.var), func, EX(func)->op_array.scope, called_scope, object); - + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = Z_OBJ_P(EX_VAR(opline->result.var)); + GC_ADDREF(closure); + CACHE_PTR(opline->extended_value, closure); + zend_stack_push(&EG(lambda_cache), &closure); + } ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4c830f203bfb..58cd0ddf916e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5916,33 +5916,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_CLASS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_function *func; - zval *object; - zend_class_entry *called_scope; - - func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; - if (Z_TYPE(EX(This)) == IS_OBJECT) { - called_scope = Z_OBJCE(EX(This)); - if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) || - (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { - object = NULL; - } else { - object = &EX(This); - } - } else { - called_scope = Z_CE(EX(This)); - object = NULL; - } - SAVE_OPLINE(); - zend_create_closure(EX_VAR(opline->result.var), func, - EX(func)->op_array.scope, called_scope, object); - - ZEND_VM_NEXT_OPCODE(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -32928,6 +32901,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CLONE_SPEC_UN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_function *func; + zval *object; + zend_class_entry *called_scope; + + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + ZEND_VM_NEXT_OPCODE(); + } + } + + func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) || + (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { + object = NULL; + } else { + object = &EX(This); + } + } else { + called_scope = Z_CE(EX(This)); + object = NULL; + } + SAVE_OPLINE(); + zend_create_closure(EX_VAR(opline->result.var), func, + EX(func)->op_array.scope, called_scope, object); + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = Z_OBJ_P(EX_VAR(opline->result.var)); + GC_ADDREF(closure); + CACHE_PTR(opline->extended_value, closure); + zend_stack_push(&EG(lambda_cache), &closure); + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; @@ -58748,33 +58761,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_CLASS_SPEC ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_function *func; - zval *object; - zend_class_entry *called_scope; - - func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; - if (Z_TYPE(EX(This)) == IS_OBJECT) { - called_scope = Z_OBJCE(EX(This)); - if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) || - (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { - object = NULL; - } else { - object = &EX(This); - } - } else { - called_scope = Z_CE(EX(This)); - object = NULL; - } - SAVE_OPLINE(); - zend_create_closure(EX_VAR(opline->result.var), func, - EX(func)->op_array.scope, called_scope, object); - - ZEND_VM_NEXT_OPCODE(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -85558,6 +85544,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CLONE_SPEC_UNUSED_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_function *func; + zval *object; + zend_class_entry *called_scope; + + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = CACHED_PTR(opline->extended_value); + if (closure) { + ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure); + ZEND_VM_NEXT_OPCODE(); + } + } + + func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) || + (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { + object = NULL; + } else { + object = &EX(This); + } + } else { + called_scope = Z_CE(EX(This)); + object = NULL; + } + SAVE_OPLINE(); + zend_create_closure(EX_VAR(opline->result.var), func, + EX(func)->op_array.scope, called_scope, object); + if (opline->extended_value != (uint32_t)-1) { + zend_object *closure = Z_OBJ_P(EX_VAR(opline->result.var)); + GC_ADDREF(closure); + CACHE_PTR(opline->extended_value, closure); + zend_stack_push(&EG(lambda_cache), &closure); + } + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; @@ -109287,7 +109313,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_MAKE_REF_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_DECLARE_FUNCTION_SPEC_LABEL, - (void*)&&ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_LABEL, + (void*)&&ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_LABEL, (void*)&&ZEND_DECLARE_CONST_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_DECLARE_CLASS_SPEC_CONST_LABEL, (void*)&&ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_LABEL, @@ -111298,11 +111324,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_DECLARE_CLASS_SPEC_CONST) HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST): - VM_TRACE(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST) - ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST) - HYBRID_BREAK(); HYBRID_CASE(ZEND_YIELD_FROM_SPEC_CONST): VM_TRACE(ZEND_YIELD_FROM_SPEC_CONST) ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -114122,6 +114143,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_CLONE_SPEC_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED): + VM_TRACE(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED) + ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_FETCH_CLASS_NAME_SPEC_UNUSED): VM_TRACE(ZEND_FETCH_CLASS_NAME_SPEC_UNUSED) ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -118255,7 +118281,7 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLER, ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_HANDLER, + ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_HANDLER, ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER, @@ -121743,7 +121769,7 @@ void zend_vm_init(void) ZEND_NULL_TAILCALL_HANDLER, ZEND_MAKE_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER, ZEND_DECLARE_FUNCTION_SPEC_TAILCALL_HANDLER, - ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_TAILCALL_HANDLER, + ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED_TAILCALL_HANDLER, ZEND_DECLARE_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER, ZEND_DECLARE_CLASS_SPEC_CONST_TAILCALL_HANDLER, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_TAILCALL_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 503a6d25634b..4586fd861021 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -910,7 +910,7 @@ _(2282, ZEND_MAKE_REF_SPEC_VAR_UNUSED) \ _(2284, ZEND_MAKE_REF_SPEC_CV_UNUSED) \ _(2285, ZEND_DECLARE_FUNCTION_SPEC) \ - _(2286, ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST) \ + _(2286, ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_UNUSED) \ _(2287, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \ _(2288, ZEND_DECLARE_CLASS_SPEC_CONST) \ _(2289, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index f9b30edb5e9b..cc14862ebedd 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -381,7 +381,7 @@ static uint32_t zend_vm_opcodes_flags[214] = { 0x00000000, 0x00000101, 0x00001000, - 0x00001003, + 0x01041001, 0x00000303, 0x00000003, 0x00000303, diff --git a/ext/opcache/tests/array_map_foreach_optimization_008.phpt b/ext/opcache/tests/array_map_foreach_optimization_008.phpt index 36c80b460e88..e90980922cab 100644 --- a/ext/opcache/tests/array_map_foreach_optimization_008.phpt +++ b/ext/opcache/tests/array_map_foreach_optimization_008.phpt @@ -56,7 +56,7 @@ $_main: ; (lines=4, args=0, vars=1, tmps=%d) ; (after optimizer) ; %s:1-9 -0000 T1 = DECLARE_LAMBDA_FUNCTION 0 +0000 T1 = DECLARE_LAMBDA_FUNCTION %d 0 0001 BIND_LEXICAL T1 CV0($n) 0002 FREE T1 0003 RETURN int(1) diff --git a/ext/opcache/tests/gh19867.phpt b/ext/opcache/tests/gh19867.phpt index 486a366722da..51b2aaeaf459 100644 --- a/ext/opcache/tests/gh19867.phpt +++ b/ext/opcache/tests/gh19867.phpt @@ -15,7 +15,7 @@ $_main: ; (lines=%d, args=0, vars=%d, tmps=%d) ; (after optimizer) ; %s -0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0000 T0 = DECLARE_LAMBDA_FUNCTION %d 0 0001 FREE T0 0002 RETURN int(1) @@ -23,7 +23,7 @@ $_main: ; (lines=%d, args=0, vars=%d, tmps=%d) ; (after optimizer) ; %s -0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0000 T0 = DECLARE_LAMBDA_FUNCTION %d 0 0001 RETURN T0 {closure:%s:%d}: