Commit:    6517ed021520a608a18da4653cb9c6b414121f6f
Author:    Nikita Popov <ni...@php.net>         Fri, 24 Aug 2012 13:29:40 +0200
Parents:   f45a0f31c8354947c0e2b9ea44a63fc0a2c23a01 
071580ea1f450513dba2dbf585a9498614f855e7
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=6517ed021520a608a18da4653cb9c6b414121f6f

Log:
Merge remote-tracking branch 'php-src/master' into addGeneratorsSupport

Conflicts:
        Zend/zend_vm_def.h
        Zend/zend_vm_execute.h

Changed paths:
  MM  Zend/zend_compile.c
  MM  Zend/zend_compile.h
  MM  Zend/zend_opcode.c
  MM  Zend/zend_vm_def.h
  MM  Zend/zend_vm_execute.h

diff --cc Zend/zend_vm_def.h
index f8955c5,ce1674e..975a2a7
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@@ -1840,291 -1840,296 +1840,294 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA
        ZEND_VM_NEXT_OPCODE();
  }
  
- ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
+ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
  {
-       USE_OPLINE
- 
- #if DEBUG_ZEND>=2
-       printf("Jumping to %d\n", opline->op1.opline_num);
- #endif
-       ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
-       ZEND_VM_CONTINUE(); /* CHECK_ME */
- }
+       zend_bool nested;
+       zend_op_array *op_array = EX(op_array);
  
- ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
- {
-       USE_OPLINE
-       zend_free_op free_op1;
-       zval *val;
-       int ret;
++      /* Generators go throw a different cleanup process */
++      if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) {
++              /* The generator object is stored in return_value_ptr_ptr */
++              zend_generator *generator = (zend_generator *) 
EG(return_value_ptr_ptr);
 +
-       SAVE_OPLINE();
-       val = GET_OP1_ZVAL_PTR(BP_VAR_R);
++              /* Close the generator to free up resources */
++              zend_generator_close(generator, 1 TSRMLS_CC);
 +
-       if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
-               ret = Z_LVAL_P(val);
-       } else {
-               ret = i_zend_is_true(val);
-               FREE_OP1();
-               if (UNEXPECTED(EG(exception) != NULL)) {
-                       HANDLE_EXCEPTION();
-               }
-       }
-       if (!ret) {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp to %d\n", opline->op2.opline_num);
- #endif
-               ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
-               ZEND_VM_CONTINUE();
++              /* Pass execution back to handling code */
++              ZEND_VM_RETURN();
 +      }
 +
-       ZEND_VM_NEXT_OPCODE();
- }
+       EG(current_execute_data) = EX(prev_execute_data);
+       EG(opline_ptr) = NULL;
+       if (!EG(active_symbol_table)) {
 -              zval ***cv = EX_CVs();
 -              zval ***end = cv + op_array->last_var;
 -              while (cv != end) {
 -                      if (*cv) {
 -                              zval_ptr_dtor(*cv);
 -                      }
 -                      cv++;
 -              }
++              zend_free_compiled_variables(EX_CVs(), op_array->last_var);
+       }
  
- ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY)
- {
-       USE_OPLINE
-       zend_free_op free_op1;
-       zval *val;
-       int ret;
+       if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
+               zval_ptr_dtor((zval**)&op_array->prototype);
+       }
  
-       SAVE_OPLINE();
-       val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+       nested = EX(nested);
  
-       if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
-               ret = Z_LVAL_P(val);
 -      zend_vm_stack_free(execute_data TSRMLS_CC);
++      /* For generators the execute_data is stored on the heap, for everything
++       * else it is stored on the VM stack. */
++      if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
++              efree(execute_data);
 +      } else {
-               ret = i_zend_is_true(val);
-               FREE_OP1();
-               if (UNEXPECTED(EG(exception) != NULL)) {
-                       HANDLE_EXCEPTION();
-               }
++              zend_vm_stack_free(execute_data TSRMLS_CC);
 +      }
-       if (ret) {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp to %d\n", opline->op2.opline_num);
- #endif
-               ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
-               ZEND_VM_CONTINUE();
+ 
+       if (nested) {
+               execute_data = EG(current_execute_data);
        }
+       if (nested) {
+               USE_OPLINE
  
-       ZEND_VM_NEXT_OPCODE();
- }
+               LOAD_REGS();
+               LOAD_OPLINE();
+               if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
  
- ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY)
- {
-       USE_OPLINE
-       zend_free_op free_op1;
-       zval *val;
-       int retval;
+                       EX(function_state).function = (zend_function *) 
EX(op_array);
+                       EX(function_state).arguments = NULL;
+                       EX(object) = EX(current_object);
  
-       SAVE_OPLINE();
-       val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+                       EG(opline_ptr) = &EX(opline);
+                       EG(active_op_array) = EX(op_array);
+                       EG(return_value_ptr_ptr) = EX(original_return_value);
+                       destroy_op_array(op_array TSRMLS_CC);
+                       efree(op_array);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               zend_throw_exception_internal(NULL TSRMLS_CC);
+                               HANDLE_EXCEPTION_LEAVE();
+                       } else if (RETURN_VALUE_USED(opline)) {
+                               if (!EX_T(opline->result.var).var.ptr) { /* 
there was no return statement */
+                                       zval *retval;
  
-       if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
-               retval = Z_LVAL_P(val);
-       } else {
-               retval = i_zend_is_true(val);
-               FREE_OP1();
-               if (UNEXPECTED(EG(exception) != NULL)) {
-                       HANDLE_EXCEPTION();
-               }
-       }
-       if (EXPECTED(retval != 0)) {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp on true to %d\n", 
opline->extended_value);
- #endif
-               
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
-               ZEND_VM_CONTINUE(); /* CHECK_ME */
-       } else {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp on false to %d\n", 
opline->op2.opline_num);
- #endif
-               
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
-               ZEND_VM_CONTINUE(); /* CHECK_ME */
-       }
- }
+                                       ALLOC_ZVAL(retval);
+                                       ZVAL_BOOL(retval, 1);
+                                       INIT_PZVAL(retval);
+                                       EX_T(opline->result.var).var.ptr = 
retval;
+                               }
+                       }
  
- ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY)
- {
-       USE_OPLINE
-       zend_free_op free_op1;
-       zval *val;
-       int retval;
+                       ZEND_VM_INC_OPCODE();
+                       ZEND_VM_LEAVE();
+               } else {
 -
+                       EG(opline_ptr) = &EX(opline);
+                       EG(active_op_array) = EX(op_array);
+                       EG(return_value_ptr_ptr) = EX(original_return_value);
+                       if (EG(active_symbol_table)) {
 -                              if 
(EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
 -                                      
zend_hash_destroy(EG(active_symbol_table));
 -                                      FREE_HASHTABLE(EG(active_symbol_table));
 -                              } else {
 -                                      /* clean before putting into the cache, 
since clean
 -                                         could call dtors, which could use 
cached hash */
 -                                      
zend_hash_clean(EG(active_symbol_table));
 -                                      *(++EG(symtable_cache_ptr)) = 
EG(active_symbol_table);
 -                              }
++                              
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
+                       }
+                       EG(active_symbol_table) = EX(symbol_table);
  
-       SAVE_OPLINE();
-       val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+                       EX(function_state).function = (zend_function *) 
EX(op_array);
+                       EX(function_state).arguments = NULL;
  
-       if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
-               retval = Z_LVAL_P(val);
-       } else {
-               retval = i_zend_is_true(val);
-               FREE_OP1();
-               if (UNEXPECTED(EG(exception) != NULL)) {
-                       HANDLE_EXCEPTION();
-               }
-       }
-       Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
-       Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
-       if (!retval) {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp to %d\n", opline->op2.opline_num);
- #endif
-               ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
-               ZEND_VM_CONTINUE();
-       }
-       ZEND_VM_NEXT_OPCODE();
- }
+                       if (EG(This)) {
+                               if (UNEXPECTED(EG(exception) != NULL) && 
IS_CTOR_CALL(EX(called_scope))) {
+                                       if (IS_CTOR_USED(EX(called_scope))) {
+                                               Z_DELREF_P(EG(This));
+                                       }
+                                       if (Z_REFCOUNT_P(EG(This)) == 1) {
+                                               
zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
+                                       }
+                               }
+                               zval_ptr_dtor(&EG(This));
+                       }
+                       EG(This) = EX(current_this);
+                       EG(scope) = EX(current_scope);
+                       EG(called_scope) = EX(current_called_scope);
  
- ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|VAR|CV, ANY)
- {
-       USE_OPLINE
-       zend_free_op free_op1;
-       zval *val;
-       int retval;
+                       EX(object) = EX(current_object);
+                       EX(called_scope) = DECODE_CTOR(EX(called_scope));
  
-       SAVE_OPLINE();
-       val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+                       zend_vm_stack_clear_multiple(TSRMLS_C);
  
-       if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
-               retval = Z_LVAL_P(val);
-       } else {
-               retval = i_zend_is_true(val);
-               FREE_OP1();
-               if (UNEXPECTED(EG(exception) != NULL)) {
-                       HANDLE_EXCEPTION();
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               zend_throw_exception_internal(NULL TSRMLS_CC);
+                               if (RETURN_VALUE_USED(opline) && 
EX_T(opline->result.var).var.ptr) {
+                                       
zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+                               }
+                               HANDLE_EXCEPTION_LEAVE();
+                       }
+ 
+                       ZEND_VM_INC_OPCODE();
+                       ZEND_VM_LEAVE();
                }
        }
-       Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
-       Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
-       if (retval) {
- #if DEBUG_ZEND>=2
-               printf("Conditional jmp to %d\n", opline->op2.opline_num);
- #endif
-               ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
-               ZEND_VM_CONTINUE();
-       }
-       ZEND_VM_NEXT_OPCODE();
+       ZEND_VM_RETURN();
  }
  
- ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY)
+ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
  {
        USE_OPLINE
+       zend_bool should_change_scope = 0;
+       zend_function *fbc = EX(function_state).function;
  
        SAVE_OPLINE();
-       if (OP1_TYPE == IS_TMP_VAR) {
-               zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
-       } else {
-               zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+       if (UNEXPECTED((fbc->common.fn_flags & 
(ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 
0)) {
+                       zend_error_noreturn(E_ERROR, "Cannot call abstract 
method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
+                       CHECK_EXCEPTION();
+                       ZEND_VM_NEXT_OPCODE(); /* Never reached */
+               }
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 
0)) {
+                       zend_error(E_DEPRECATED, "Function %s%s%s() is 
deprecated",
+                               fbc->common.scope ? fbc->common.scope->name : 
"",
+                               fbc->common.scope ? "::" : "",
+                               fbc->common.function_name);
+               }
        }
-       CHECK_EXCEPTION();
-       ZEND_VM_NEXT_OPCODE();
- }
- 
- ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
- {
-       USE_OPLINE
-       zval *tmp = &EX_T(opline->result.var).tmp_var;
- 
-       SAVE_OPLINE();
-       tmp->value.str.val = emalloc(1);
-       tmp->value.str.val[0] = 0;
-       tmp->value.str.len = 0;
-       Z_SET_REFCOUNT_P(tmp, 1);
-       tmp->type = IS_STRING;
-       Z_UNSET_ISREF_P(tmp);
-       /*CHECK_EXCEPTION();*/
-       ZEND_VM_NEXT_OPCODE();
- }
- 
- ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
- {
-       USE_OPLINE
-       zval *str = &EX_T(opline->result.var).tmp_var;
- 
-       SAVE_OPLINE();
+       if (fbc->common.scope &&
+               !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
+               !EX(object)) {
  
-       if (OP1_TYPE == IS_UNUSED) {
-               /* Initialize for erealloc in add_char_to_string */
-               Z_STRVAL_P(str) = NULL;
-               Z_STRLEN_P(str) = 0;
-               Z_TYPE_P(str) = IS_STRING;
+               if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+                       /* FIXME: output identifiers properly */
+                       zend_error(E_STRICT, "Non-static method %s::%s() should 
not be called statically", fbc->common.scope->name, fbc->common.function_name);
+               } else {
+                       /* FIXME: output identifiers properly */
+                       /* An internal function assumes $this is present and 
won't check that. So PHP would crash by allowing the call. */
+                       zend_error_noreturn(E_ERROR, "Non-static method 
%s::%s() cannot be called statically", fbc->common.scope->name, 
fbc->common.function_name);
+               }
+       }
  
-               INIT_PZVAL(str);
+       if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
+               should_change_scope = 1;
+               EX(current_this) = EG(This);
+               EX(current_scope) = EG(scope);
+               EX(current_called_scope) = EG(called_scope);
+               EG(This) = EX(object);
+               EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? 
fbc->common.scope : NULL;
+               EG(called_scope) = EX(called_scope);
        }
  
-       add_char_to_string(str, str, opline->op2.zv);
+       zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), 
&EX(current_object), &EX(fbc));
+       EX(function_state).arguments = 
zend_vm_stack_push_args(opline->extended_value TSRMLS_CC);
+       LOAD_OPLINE();
  
-       /* FREE_OP is missing intentionally here - we're always working on the 
same temporary variable */
-       /*CHECK_EXCEPTION();*/
-       ZEND_VM_NEXT_OPCODE();
- }
+       if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+               temp_variable *ret = &EX_T(opline->result.var);
  
- ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
- {
-       USE_OPLINE
-       zval *str = &EX_T(opline->result.var).tmp_var;
+               MAKE_STD_ZVAL(ret->var.ptr);
+               ZVAL_NULL(ret->var.ptr);
+               ret->var.ptr_ptr = &ret->var.ptr;
+               ret->var.fcall_returned_reference = (fbc->common.fn_flags & 
ZEND_ACC_RETURN_REFERENCE) != 0;
+ 
+               if (fbc->common.arg_info) {
+                       zend_uint i=0;
+                       zval **p = (zval**)EX(function_state).arguments;
+                       ulong arg_count = opline->extended_value;
  
-       SAVE_OPLINE();
+                       while (arg_count>0) {
+                               zend_verify_arg_type(fbc, ++i, *(p-arg_count), 
0 TSRMLS_CC);
+                               arg_count--;
+                       }
+               }
  
-       if (OP1_TYPE == IS_UNUSED) {
-               /* Initialize for erealloc in add_string_to_string */
-               Z_STRVAL_P(str) = NULL;
-               Z_STRLEN_P(str) = 0;
-               Z_TYPE_P(str) = IS_STRING;
+               if (!zend_execute_internal) {
+                       /* saves one function call if zend_execute_internal is 
not used */
+                       fbc->internal_function.handler(opline->extended_value, 
ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? 
&ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+               } else {
+                       zend_execute_internal(EXECUTE_DATA, 
RETURN_VALUE_USED(opline) TSRMLS_CC);
+               }
  
-               INIT_PZVAL(str);
-       }
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(&ret->var.ptr);
+               }
+       } else if (fbc->type == ZEND_USER_FUNCTION) {
+               EX(original_return_value) = EG(return_value_ptr_ptr);
+               EG(active_symbol_table) = NULL;
+               EG(active_op_array) = &fbc->op_array;
+               EG(return_value_ptr_ptr) = NULL;
+               if (RETURN_VALUE_USED(opline)) {
+                       temp_variable *ret = &EX_T(opline->result.var);
  
-       add_string_to_string(str, str, opline->op2.zv);
+                       ret->var.ptr = NULL;
+                       EG(return_value_ptr_ptr) = &ret->var.ptr;
+                       ret->var.ptr_ptr = &ret->var.ptr;
+                       ret->var.fcall_returned_reference = 
(fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+               }
  
-       /* FREE_OP is missing intentionally here - we're always working on the 
same temporary variable */
-       /*CHECK_EXCEPTION();*/
-       ZEND_VM_NEXT_OPCODE();
- }
 -              if (EXPECTED(zend_execute == execute)) {
++              if (EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
++                      if (RETURN_VALUE_USED(opline)) {
++                              EX_T(opline->result.var).var.ptr = 
zend_generator_create_zval(EG(active_op_array) TSRMLS_CC);
++                      }
++              } else if (EXPECTED(zend_execute == execute)) {
+                       if (EXPECTED(EG(exception) == NULL)) {
+                               ZEND_VM_ENTER();
+                       }
+               } else {
+                       zend_execute(EG(active_op_array) TSRMLS_CC);
+               }
  
- ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
- {
-       USE_OPLINE
-       zend_free_op free_op2;
-       zval *str = &EX_T(opline->result.var).tmp_var;
-       zval *var;
-       zval var_copy;
-       int use_copy = 0;
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               EG(return_value_ptr_ptr) = EX(original_return_value);
+               if (EG(active_symbol_table)) {
 -                      if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
 -                              zend_hash_destroy(EG(active_symbol_table));
 -                              FREE_HASHTABLE(EG(active_symbol_table));
 -                      } else {
 -                              /* clean before putting into the cache, since 
clean
 -                                 could call dtors, which could use cached 
hash */
 -                              zend_hash_clean(EG(active_symbol_table));
 -                              *(++EG(symtable_cache_ptr)) = 
EG(active_symbol_table);
 -                      }
++                      
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
+               }
+               EG(active_symbol_table) = EX(symbol_table);
+       } else { /* ZEND_OVERLOADED_FUNCTION */
+               MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
+               ZVAL_NULL(EX_T(opline->result.var).var.ptr);
  
-       SAVE_OPLINE();
-       var = GET_OP2_ZVAL_PTR(BP_VAR_R);
 -                      /* Not sure what should be done here if it's a static 
method */
++              /* Not sure what should be done here if it's a static method */
+               if (EXPECTED(EX(object) != NULL)) {
+                       
Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, 
opline->extended_value, EX_T(opline->result.var).var.ptr, 
&EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) 
TSRMLS_CC);
+               } else {
+                       zend_error_noreturn(E_ERROR, "Cannot call overloaded 
function for non-object");
+               }
  
-       if (OP1_TYPE == IS_UNUSED) {
-               /* Initialize for erealloc in add_string_to_string */
-               Z_STRVAL_P(str) = NULL;
-               Z_STRLEN_P(str) = 0;
-               Z_TYPE_P(str) = IS_STRING;
+               if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+                       efree((char*)fbc->common.function_name);
+               }
+               efree(fbc);
  
-               INIT_PZVAL(str);
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+               } else {
+                       Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+                       Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+                       EX_T(opline->result.var).var.fcall_returned_reference = 
0;
+                       EX_T(opline->result.var).var.ptr_ptr = 
&EX_T(opline->result.var).var.ptr;
+               }
        }
  
-       if (Z_TYPE_P(var) != IS_STRING) {
-               zend_make_printable_zval(var, &var_copy, &use_copy);
+       EX(function_state).function = (zend_function *) EX(op_array);
+       EX(function_state).arguments = NULL;
  
-               if (use_copy) {
-                       var = &var_copy;
+       if (should_change_scope) {
+               if (EG(This)) {
+                       if (UNEXPECTED(EG(exception) != NULL) && 
IS_CTOR_CALL(EX(called_scope))) {
+                               if (IS_CTOR_USED(EX(called_scope))) {
+                                       Z_DELREF_P(EG(This));
+                               }
+                               if (Z_REFCOUNT_P(EG(This)) == 1) {
+                                       zend_object_store_ctor_failed(EG(This) 
TSRMLS_CC);
+                               }
+                       }
+                       zval_ptr_dtor(&EG(This));
                }
+               EG(This) = EX(current_this);
+               EG(scope) = EX(current_scope);
+               EG(called_scope) = EX(current_called_scope);
        }
-       add_string_to_string(str, str, var);
  
-       if (use_copy) {
-               zval_dtor(var);
+       EX(object) = EX(current_object);
+       EX(called_scope) = DECODE_CTOR(EX(called_scope));
+ 
+       zend_vm_stack_clear_multiple(TSRMLS_C);
+ 
+       if (UNEXPECTED(EG(exception) != NULL)) {
+               zend_throw_exception_internal(NULL TSRMLS_CC);
+               if (RETURN_VALUE_USED(opline) && 
EX_T(opline->result.var).var.ptr) {
+                       zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+               }
+               HANDLE_EXCEPTION();
        }
-       /* original comment, possibly problematic:
-        * FREE_OP is missing intentionally here - we're always working on the 
same temporary variable
-        * (Zeev):  I don't think it's problematic, we only use variables
-        * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
-        * string offsets or overloaded objects
-        */
-       FREE_OP2();
  
-       CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
  }
  
@@@ -5346,206 -5350,26 +5376,184 @@@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR
  
  ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY)
  {
-       USE_OPLINE
-       zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
- 
-       SAVE_OPLINE();
        zend_exception_restore(TSRMLS_C);
-       if (EX(leaving)) {
-               zend_uint catch_op_num = 0, finally_op_num = 0;
-               for (i = 0; i < EX(leaving); i++) {
-                       if (EG(active_op_array)->try_catch_array[i].try_op > 
op_num) {
-                               break;
-                       } 
-                       if (op_num < 
EG(active_op_array)->try_catch_array[i].finally_op) {
-                               finally_op_num = 
EG(active_op_array)->try_catch_array[i].finally_op;
-                       }
-                       if (EG(exception)) {
-                               if (op_num < 
EG(active_op_array)->try_catch_array[i].catch_op) {
-                                       catch_op_num = 
EG(active_op_array)->try_catch_array[i].catch_op;
-                               }
-                       }
-               }
- 
-               if (catch_op_num && finally_op_num) {
-                       if (catch_op_num > finally_op_num) {
-                               
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
-                               ZEND_VM_CONTINUE();
-                       } else {
-                               EX(leaving) = 0;
-                               
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
-                               ZEND_VM_CONTINUE();
-                       }
-               } else if (catch_op_num) {
-                       
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
-                       ZEND_VM_CONTINUE();
-               } else if (finally_op_num) {
-                       
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
-                       ZEND_VM_CONTINUE();
-               } else {
-                       ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
-               }
-       } else {
+       if (!EX(leaving)) {
                ZEND_VM_NEXT_OPCODE();
+       } else {
+               zend_uint leaving = EX(leaving);
+               switch (leaving) {
+                       case ZEND_RETURN:
+                       case ZEND_RETURN_BY_REF:
+                       case ZEND_THROW:
+                               leaving = ZEND_LEAVE;
+                       case ZEND_JMP:
+                       case ZEND_BRK:
+                       case ZEND_CONT:
+                       case ZEND_GOTO:
+                                
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, leaving);
+                       break;
+               }
        }
+ 
+       ZEND_VM_CONTINUE();
  }
  
 +ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, 
CONST|TMP|VAR|CV|UNUSED)
 +{
 +      USE_OPLINE
 +
 +      /* The generator object is stored in return_value_ptr_ptr */
 +      zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
 +
 +      /* Destroy the previously yielded value */
 +      if (generator->value) {
 +              zval_ptr_dtor(&generator->value);
 +      }
 +
 +      /* Destroy the previously yielded key */
 +      if (generator->key) {
 +              zval_ptr_dtor(&generator->key);
 +      }
 +
 +      /* Set the new yielded value */
 +      if (OP1_TYPE != IS_UNUSED) {
 +              zend_free_op free_op1;
 +
 +              if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
 +                      /* Constants and temporary variables aren't yieldable 
by reference,
 +                       * but we still allow them with a notice. */
 +                      if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
 +                              zval *value, *copy;
 +
 +                              zend_error(E_NOTICE, "Only variable references 
should be yielded by reference");
 +
 +                              value = GET_OP1_ZVAL_PTR(BP_VAR_R);
 +                              ALLOC_ZVAL(copy);
 +                              INIT_PZVAL_COPY(copy, value);
 +
 +                              /* Temporary variables don't need ctor copying 
*/
 +                              if (!IS_OP1_TMP_FREE()) {
 +                                      zval_copy_ctor(copy);
 +                              }
 +
 +                              generator->value = copy;
 +                      } else {
 +                              zval **value_ptr = 
GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
 +
 +                              if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr 
== NULL)) {
 +                                      zend_error_noreturn(E_ERROR, "Cannot 
yield string offsets by reference");
 +                              }
 +
 +                              /* If a function call result is yielded and the 
function did
 +                               * not return by reference we throw a notice. */
 +                              if (OP1_TYPE == IS_VAR && !Z_ISREF_PP(value_ptr)
 +                                  && !(opline->extended_value == 
ZEND_RETURNS_FUNCTION
 +                                       && 
EX_T(opline->op1.var).var.fcall_returned_reference)
 +                                  && EX_T(opline->op1.var).var.ptr_ptr == 
&EX_T(opline->op1.var).var.ptr) {
 +                                      zend_error(E_NOTICE, "Only variable 
references should be yielded by reference");
 +
 +                                      Z_ADDREF_PP(value_ptr);
 +                                      generator->value = *value_ptr;
 +                              } else {
 +                                      SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
 +                                      Z_ADDREF_PP(value_ptr);
 +                                      generator->value = *value_ptr;
 +                              }
 +
 +                              FREE_OP1_IF_VAR();
 +                      }
 +              } else {
 +                      zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
 +
 +                      /* Consts, temporary variables and references need 
copying */
 +                      if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR
 +                              || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) 
> 0)
 +                      ) {
 +                              zval *copy;
 +
 +                              ALLOC_ZVAL(copy);
 +                              INIT_PZVAL_COPY(copy, value);
 +
 +                              /* Temporary variables don't need ctor copying 
*/
 +                              if (!IS_OP1_TMP_FREE()) {
 +                                      zval_copy_ctor(copy);
 +                              }
 +
 +                              generator->value = copy;
 +                      } else {
 +                              Z_ADDREF_P(value);
 +                              generator->value = value;
 +                      }
 +
 +                      FREE_OP1_IF_VAR();
 +              }
 +      } else {
 +              /* If no value was specified yield null */
 +              Z_ADDREF(EG(uninitialized_zval));
 +              generator->value = &EG(uninitialized_zval);
 +      }
 +
 +      /* Set the new yielded key */
 +      if (OP2_TYPE != IS_UNUSED) {
 +              zend_free_op free_op2;
 +              zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R);
 +
 +              /* Consts, temporary variables and references need copying */
 +              if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_TMP_VAR
 +                      || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0)
 +              ) {
 +                      zval *copy;
 +
 +                      ALLOC_ZVAL(copy);
 +                      INIT_PZVAL_COPY(copy, key);
 +
 +                      /* Temporary variables don't need ctor copying */
 +                      if (!IS_OP1_TMP_FREE()) {
 +                              zval_copy_ctor(copy);
 +                      }
 +
 +                      generator->key = copy;
 +              } else {
 +                      Z_ADDREF_P(key);
 +                      generator->key = key;
 +              }
 +
 +              if (Z_TYPE_P(generator->key) == IS_LONG
 +                  && Z_LVAL_P(generator->key) > 
generator->largest_used_integer_key
 +              ) {
 +                      generator->largest_used_integer_key = 
Z_LVAL_P(generator->key);
 +              }
 +
 +              FREE_OP2_IF_VAR();
 +      } else {
 +              /* If no key was specified we use auto-increment keys */
 +              generator->largest_used_integer_key++;
 +
 +              ALLOC_INIT_ZVAL(generator->key);
 +              ZVAL_LONG(generator->key, generator->largest_used_integer_key);
 +      }
 +
 +      /* If a value is sent it should go into the result var */
 +      generator->send_target = &EX_T(opline->result.var);
 +
 +      /* Initialize the sent value to NULL */
 +      Z_ADDREF(EG(uninitialized_zval));
 +      AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
 +
 +      /* We increment to the next op, so we are at the correct position when 
the
 +       * generator is resumed. */
 +      ZEND_VM_INC_OPCODE();
 +
 +      /* The GOTO VM uses a local opline variable. We need to set the opline
 +       * variable in execute_data so we don't resume at an old position. */
 +      SAVE_OPLINE();
 +
 +      ZEND_VM_RETURN();
 +}
 +
 +ZEND_VM_HANDLER(161, ZEND_DELEGATE_YIELD, CONST|TMP|VAR|CV, ANY)
 +{
 +      ZEND_VM_NEXT_OPCODE();
 +}
 +
  ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
diff --cc Zend/zend_vm_execute.h
index 8d2b7bf,bd19124..402442f
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@@ -457,40 -427,6 +457,13 @@@ ZEND_API void execute_ex(zend_execute_d
        zend_error_noreturn(E_ERROR, "Arrived at end of main loop which 
shouldn't happen");
  }
  
 +ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
 +{
 +      zend_execute_data *execute_data = 
zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC);
 +
 +      execute_ex(execute_data TSRMLS_CC);
 +}
 +
- static int ZEND_FASTCALL  ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
- {
-       USE_OPLINE
- 
- #if DEBUG_ZEND>=2
-       printf("Jumping to %d\n", opline->op1.opline_num);
- #endif
-       ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
-       ZEND_VM_CONTINUE(); /* CHECK_ME */
- }
- 
- static int ZEND_FASTCALL  
ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
- {
-       USE_OPLINE
-       zval *tmp = &EX_T(opline->result.var).tmp_var;
- 
-       SAVE_OPLINE();
-       tmp->value.str.val = emalloc(1);
-       tmp->value.str.val[0] = 0;
-       tmp->value.str.len = 0;
-       Z_SET_REFCOUNT_P(tmp, 1);
-       tmp->type = IS_STRING;
-       Z_UNSET_ISREF_P(tmp);
-       /*CHECK_EXCEPTION();*/
-       ZEND_VM_NEXT_OPCODE();
- }
- 
  static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
  {
        zend_bool nested;
@@@ -564,7 -489,7 +537,6 @@@
                        ZEND_VM_INC_OPCODE();
                        ZEND_VM_LEAVE();
                } else {
--
                        EG(opline_ptr) = &EX(opline);
                        EG(active_op_array) = EX(op_array);
                        EG(return_value_ptr_ptr) = EX(original_return_value);
@@@ -725,7 -662,7 +697,7 @@@ static int ZEND_FASTCALL zend_do_fcall_
                MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
                ZVAL_NULL(EX_T(opline->result.var).var.ptr);
  
--                      /* Not sure what should be done here if it's a static 
method */
++              /* Not sure what should be done here if it's a static method */
                if (EXPECTED(EX(object) != NULL)) {
                        
Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, 
opline->extended_value, EX_T(opline->result.var).var.ptr, 
&EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) 
TSRMLS_CC);
                } else {
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to