}
/* }}} */
+/*
+ * Stack Frame Layout (the whole stack frame is allocated at once)
+ * ==================
+ *
+ * +========================================+
+ * | zend_execute_data |<---+
+ * | EX(function_state).arguments |--+ |
+ * | ... | | |
+ * | ARGUMENT [1] | | |
+ * | ... | | |
+ * | ARGUMENT [ARGS_NUMBER] | | |
+ * | ARGS_NUMBER |<-+ |
+ * +========================================+ |
+ * |
+ * +========================================+ |
+ * | TMP_VAR[op_arrat->T-1] | |
+ * | ... | |
+ * EX_TMP_VAR_NUM(0) ----> | TMP_VAR[0] | |
+ * +----------------------------------------+ |
+ * EG(current_execute_data) -> | zend_execute_data | |
+ * | EX(prev_execute_data) |----+
+ * +----------------------------------------+
+ * EX_CV_NUM(0) ---------> | CV[0] |--+
+ * | ... | |
+ * | CV[op_array->last_var-1] | |
+ * +----------------------------------------+ |
+ * | Optional slot for CV[0] zval* |<-+
+ * | ... |
+ * | ...for CV [op_array->last_var-1] zval* |
+ * +----------------------------------------+
+ * EX(call_slots) -> | CALL_SLOT[0] |
+ * | ... |
+ * | CALL_SLOT[op_array->nested_calls-1] |
+ * +----------------------------------------+
+ * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
+ * | ... |
+ * zend_vm_stack_top --------> | ... |
+ * | ... |
+ * | ARGUMENTS STACK [op_array->used_stack] |
+ * +----------------------------------------+
+ */
+
+zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
+{
+ zend_execute_data *execute_data;
+
+ /*
+ * When allocating the execute_data, memory for compiled variables and
+ * temporary variables is also allocated after the actual zend_execute_data
+ * struct. op_array->last_var specifies the number of compiled variables and
+ * op_array->T is the number of temporary variables. If there is no symbol
+ * table, then twice as much memory is allocated for compiled variables.
+ * In that case the first half contains zval**s and the second half the
+ * actual zval*s (which would otherwise be in the symbol table).
+ */
+ size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
+ size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));
+ size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T;
+ size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
+ size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack;
+ size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;
+
+ /*
+ * Normally the execute_data is allocated on the VM stack (because it does
+ * not actually do any allocation and thus is faster). For generators
+ * though this behavior would be suboptimal, because the (rather large)
+ * structure would have to be copied back and forth every time execution is
+ * suspended or resumed. That's why for generators the execution context
+ * is allocated using emalloc, thus allowing to save and restore it simply
+ * by replacing a pointer.
+ */
+ if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
+ /* Prepend the regular stack frame with copy on prev_execute_data
+ * and passed arguments
+ */
+ int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
+ size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1);
+
+ total_size += args_size + execute_data_size;
+
+ EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*));
+ EG(argument_stack)->prev = NULL;
+ execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + Ts_size);
+
+ /* copy prev_execute_data */
+ EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size);
+ memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
+ EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
+ EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count);
+
+ /* copy arguemnts */
+ *EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count;
+ if (args_count > 0) {
+ zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
+ zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
+ int i;
+
+ for (i = 0; i < args_count; i++) {
+ arg_dst[i] = arg_src[i];
+ Z_ADDREF_P(arg_dst[i]);
+ }
+ }
+ } else {
+ execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
+ execute_data = (zend_execute_data*)((char*)execute_data + Ts_size);
+ EX(prev_execute_data) = EG(current_execute_data);
+ }
+
+ memset(EX_CV_NUM(execute_data, 0), 0, sizeof(zval **) * op_array->last_var);
+
+ EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + CVs_size);
+
+
+ EX(op_array) = op_array;
+
+ EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data);
+
+ EX(object) = NULL;
+ EX(current_this) = NULL;
+ EX(old_error_reporting) = NULL;
+ EX(symbol_table) = EG(active_symbol_table);
+ EX(call) = NULL;
+ EG(current_execute_data) = execute_data;
+ EX(nested) = nested;
+
+ if (!op_array->run_time_cache && op_array->last_cache_slot) {
+ op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
+ }
+
+ if (op_array->this_var != -1 && EG(This)) {
+ Z_ADDREF_P(EG(This)); /* For $this pointer */
+ if (!EG(active_symbol_table)) {
+ EX_CV(op_array->this_var) = (zval **) EX_CV_NUM(execute_data, op_array->last_var + op_array->this_var);
+ *EX_CV(op_array->this_var) = EG(This);
+ } else {
+ if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) EX_CV_NUM(execute_data, op_array->this_var))==FAILURE) {
+ Z_DELREF_P(EG(This));
+ }
+ }
+ }
+
+ EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+ EG(opline_ptr) = &EX(opline);
+
+ EX(function_state).function = (zend_function *) op_array;
+ EX(function_state).arguments = NULL;
+
+ return execute_data;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
#define EX(element) execute_data->element
-/*
- * Stack Frame Layout (the whole stack frame is allocated at once)
- * ==================
- *
- * +========================================+
- * | zend_execute_data |<---+
- * | EX(function_state).arguments |--+ |
- * | ... | | |
- * | ARGUMENT [1] | | |
- * | ... | | |
- * | ARGUMENT [ARGS_NUMBER] | | |
- * | ARGS_NUMBER |<-+ |
- * +========================================+ |
- * |
- * +========================================+ |
- * | TMP_VAR[op_arrat->T-1] | |
- * | ... | |
- * EX_TMP_VAR_NUM(0) ----> | TMP_VAR[0] | |
- * +----------------------------------------+ |
- * EG(current_execute_data) -> | zend_execute_data | |
- * | EX(prev_execute_data) |----+
- * +----------------------------------------+
- * EX_CV_NUM(0) ---------> | CV[0] |--+
- * | ... | |
- * | CV[op_array->last_var-1] | |
- * +----------------------------------------+ |
- * | Optional slot for CV[0] zval* |<-+
- * | ... |
- * | ...for CV [op_array->last_var-1] zval* |
- * +----------------------------------------+
- * EX(call_slots) -> | CALL_SLOT[0] |
- * | ... |
- * | CALL_SLOT[op_array->nested_calls-1] |
- * +----------------------------------------+
- * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
- * | ... |
- * zend_vm_stack_top --------> | ... |
- * | ... |
- * | ARGUMENTS STACK [op_array->used_stack] |
- * +----------------------------------------+
- */
-
-zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC)
-{
- zend_execute_data *execute_data;
-
- /*
- * When allocating the execute_data, memory for compiled variables and
- * temporary variables is also allocated after the actual zend_execute_data
- * struct. op_array->last_var specifies the number of compiled variables and
- * op_array->T is the number of temporary variables. If there is no symbol
- * table, then twice as much memory is allocated for compiled variables.
- * In that case the first half contains zval**s and the second half the
- * actual zval*s (which would otherwise be in the symbol table).
- */
- size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
- size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));
- size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T;
- size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
- size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack;
- size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;
-
- /*
- * Normally the execute_data is allocated on the VM stack (because it does
- * not actually do any allocation and thus is faster). For generators
- * though this behavior would be suboptimal, because the (rather large)
- * structure would have to be copied back and forth every time execution is
- * suspended or resumed. That's why for generators the execution context
- * is allocated using emalloc, thus allowing to save and restore it simply
- * by replacing a pointer.
- */
- if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
- /* Prepend the regular stack frame with copy on prev_execute_data
- * and passed arguments
- */
- int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
- size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1);
-
- total_size += args_size + execute_data_size;
-
- EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*));
- EG(argument_stack)->prev = NULL;
- execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + Ts_size);
-
- /* copy prev_execute_data */
- EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size);
- memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
- EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
- EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count);
-
- /* copy arguemnts */
- *EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count;
- if (args_count > 0) {
- zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
- zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
- int i;
-
- for (i = 0; i < args_count; i++) {
- arg_dst[i] = arg_src[i];
- Z_ADDREF_P(arg_dst[i]);
- }
- }
- } else {
- execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
- execute_data = (zend_execute_data*)((char*)execute_data + Ts_size);
- EX(prev_execute_data) = EG(current_execute_data);
- }
-
- memset(EX_CV_NUM(execute_data, 0), 0, sizeof(zval **) * op_array->last_var);
-
- EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + CVs_size);
-
-
- EX(op_array) = op_array;
-
- EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data);
-
- EX(object) = NULL;
- EX(current_this) = NULL;
- EX(old_error_reporting) = NULL;
- EX(symbol_table) = EG(active_symbol_table);
- EX(call) = NULL;
- EG(current_execute_data) = execute_data;
- EX(nested) = nested;
-
- if (!op_array->run_time_cache && op_array->last_cache_slot) {
- op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
- }
-
- if (op_array->this_var != -1 && EG(This)) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- if (!EG(active_symbol_table)) {
- EX_CV(op_array->this_var) = (zval **) EX_CV_NUM(execute_data, op_array->last_var + op_array->this_var);
- *EX_CV(op_array->this_var) = EG(This);
- } else {
- if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) EX_CV_NUM(execute_data, op_array->this_var))==FAILURE) {
- Z_DELREF_P(EG(This));
- }
- }
- }
-
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
- EG(opline_ptr) = &EX(opline);
-
- EX(function_state).function = (zend_function *) op_array;
- EX(function_state).arguments = NULL;
-
- return execute_data;
-}
-
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
{
DCL_OPLINE
{%DEFINES%}
-/*
- * Stack Frame Layout (the whole stack frame is allocated at once)
- * ==================
- *
- * +========================================+
- * | zend_execute_data |<---+
- * | EX(function_state).arguments |--+ |
- * | ... | | |
- * | ARGUMENT [1] | | |
- * | ... | | |
- * | ARGUMENT [ARGS_NUMBER] | | |
- * | ARGS_NUMBER |<-+ |
- * +========================================+ |
- * |
- * +========================================+ |
- * | TMP_VAR[op_arrat->T-1] | |
- * | ... | |
- * EX_TMP_VAR_NUM(0) ----> | TMP_VAR[0] | |
- * +----------------------------------------+ |
- * EG(current_execute_data) -> | zend_execute_data | |
- * | EX(prev_execute_data) |----+
- * +----------------------------------------+
- * EX_CV_NUM(0) ---------> | CV[0] |--+
- * | ... | |
- * | CV[op_array->last_var-1] | |
- * +----------------------------------------+ |
- * | Optional slot for CV[0] zval* |<-+
- * | ... |
- * | ...for CV [op_array->last_var-1] zval* |
- * +----------------------------------------+
- * EX(call_slots) -> | CALL_SLOT[0] |
- * | ... |
- * | CALL_SLOT[op_array->nested_calls-1] |
- * +----------------------------------------+
- * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
- * | ... |
- * zend_vm_stack_top --------> | ... |
- * | ... |
- * | ARGUMENTS STACK [op_array->used_stack] |
- * +----------------------------------------+
- */
-
-zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC)
-{
- zend_execute_data *execute_data;
-
- /*
- * When allocating the execute_data, memory for compiled variables and
- * temporary variables is also allocated after the actual zend_execute_data
- * struct. op_array->last_var specifies the number of compiled variables and
- * op_array->T is the number of temporary variables. If there is no symbol
- * table, then twice as much memory is allocated for compiled variables.
- * In that case the first half contains zval**s and the second half the
- * actual zval*s (which would otherwise be in the symbol table).
- */
- size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
- size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));
- size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T;
- size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
- size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack;
- size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;
-
- /*
- * Normally the execute_data is allocated on the VM stack (because it does
- * not actually do any allocation and thus is faster). For generators
- * though this behavior would be suboptimal, because the (rather large)
- * structure would have to be copied back and forth every time execution is
- * suspended or resumed. That's why for generators the execution context
- * is allocated using emalloc, thus allowing to save and restore it simply
- * by replacing a pointer.
- */
- if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
- /* Prepend the regular stack frame with copy on prev_execute_data
- * and passed arguments
- */
- int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
- size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1);
-
- total_size += args_size + execute_data_size;
-
- EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*));
- EG(argument_stack)->prev = NULL;
- execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + Ts_size);
-
- /* copy prev_execute_data */
- EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size);
- memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
- EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
- EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count);
-
- /* copy arguemnts */
- *EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count;
- if (args_count > 0) {
- zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
- zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
- int i;
-
- for (i = 0; i < args_count; i++) {
- arg_dst[i] = arg_src[i];
- Z_ADDREF_P(arg_dst[i]);
- }
- }
- } else {
- execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
- execute_data = (zend_execute_data*)((char*)execute_data + Ts_size);
- EX(prev_execute_data) = EG(current_execute_data);
- }
-
- memset(EX_CV_NUM(execute_data, 0), 0, sizeof(zval **) * op_array->last_var);
-
- EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + CVs_size);
-
-
- EX(op_array) = op_array;
-
- EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data);
-
- EX(object) = NULL;
- EX(current_this) = NULL;
- EX(old_error_reporting) = NULL;
- EX(symbol_table) = EG(active_symbol_table);
- EX(call) = NULL;
- EG(current_execute_data) = execute_data;
- EX(nested) = nested;
-
- if (!op_array->run_time_cache && op_array->last_cache_slot) {
- op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
- }
-
- if (op_array->this_var != -1 && EG(This)) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- if (!EG(active_symbol_table)) {
- EX_CV(op_array->this_var) = (zval **) EX_CV_NUM(execute_data, op_array->last_var + op_array->this_var);
- *EX_CV(op_array->this_var) = EG(This);
- } else {
- if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) EX_CV_NUM(execute_data, op_array->this_var))==FAILURE) {
- Z_DELREF_P(EG(This));
- }
- }
- }
-
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
- EG(opline_ptr) = &EX(opline);
-
- EX(function_state).function = (zend_function *) op_array;
- EX(function_state).arguments = NULL;
-
- return execute_data;
-}
-
ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
{
DCL_OPLINE