}
OBJ_RELEASE(object);
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
- OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype);
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
- zend_vm_stack_free_extra_args_ex(call_info, execute_data);
old_execute_data = execute_data;
execute_data = EX(prev_execute_data);
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
#endif
#endif
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
- zend_vm_stack_free_extra_args_ex(call_info, execute_data);
+zend_leave_helper_SPEC_LABEL:
+{
+ zend_execute_data *old_execute_data;
+ uint32_t call_info = EX_CALL_INFO();
+
+ if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED)) == 0)) {
+ i_free_compiled_variables(execute_data);
+
+ EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
+ zend_object *object = Z_OBJ(execute_data->This);
+#if 0
+ if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+#else
+ if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
+#endif
+ GC_DELREF(object);
+ zend_object_store_ctor_failed(object);
+ }
+ OBJ_RELEASE(object);
+ } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
+ }
+ EG(vm_stack_top) = (zval*)execute_data;
+ execute_data = EX(prev_execute_data);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_rethrow_exception(execute_data);
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ LOAD_NEXT_OPLINE();
+ ZEND_VM_LEAVE();
+ } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
+ i_free_compiled_variables(execute_data);
+
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table));
+ }
+ EG(current_execute_data) = EX(prev_execute_data);
++
++ /* Free extra args before releasing the closure,
++ * as that may free the op_array. */
++ zend_vm_stack_free_extra_args_ex(call_info, execute_data);
++
+ if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
+ zend_object *object = Z_OBJ(execute_data->This);
+#if 0
+ if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+#else
+ if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
+#endif
+ GC_DELREF(object);
+ zend_object_store_ctor_failed(object);
+ }
+ OBJ_RELEASE(object);
+ } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
+ }
+
+ old_execute_data = execute_data;
+ execute_data = EX(prev_execute_data);
+ zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_rethrow_exception(execute_data);
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ LOAD_NEXT_OPLINE();
+ ZEND_VM_LEAVE();
+ } else if (EXPECTED((call_info & ZEND_CALL_TOP) == 0)) {
+ zend_detach_symbol_table(execute_data);
+ destroy_op_array(&EX(func)->op_array);
+ efree_size(EX(func), sizeof(zend_op_array));
+ old_execute_data = execute_data;
+ execute_data = EG(current_execute_data) = EX(prev_execute_data);
+ zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
+
+ zend_attach_symbol_table(execute_data);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_rethrow_exception(execute_data);
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ LOAD_NEXT_OPLINE();
+ ZEND_VM_LEAVE();
+ } else {
+ if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
+ i_free_compiled_variables(execute_data);
+ if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) {
+ if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ zend_clean_and_cache_symbol_table(EX(symbol_table));
+ }
+ zend_vm_stack_free_extra_args_ex(call_info, execute_data);
+ }
+ EG(current_execute_data) = EX(prev_execute_data);
+ if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
+ OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
+ }
+ ZEND_VM_RETURN();
+ } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
+ zend_array *symbol_table = EX(symbol_table);
+
+ zend_detach_symbol_table(execute_data);
+ old_execute_data = EX(prev_execute_data);
+ while (old_execute_data) {
+ if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ if (old_execute_data->symbol_table == symbol_table) {
+ zend_attach_symbol_table(old_execute_data);
+ }
+ break;
+ }
+ old_execute_data = old_execute_data->prev_execute_data;
+ }
+ EG(current_execute_data) = EX(prev_execute_data);
+ ZEND_VM_RETURN();
+ }
+ }
+}
+
HYBRID_CASE(ZEND_JMP_SPEC):
+ VM_TRACE(ZEND_JMP_SPEC)
ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
HYBRID_CASE(ZEND_DO_ICALL_SPEC_RETVAL_UNUSED):