]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6'
authorNikita Popov <nikic@php.net>
Tue, 10 Mar 2015 17:26:09 +0000 (18:26 +0100)
committerNikita Popov <nikic@php.net>
Tue, 10 Mar 2015 17:26:09 +0000 (18:26 +0100)
Conflicts:
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

1  2 
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 5c99f1c4560d8efe59b23bff5a7f345e7f783833,0fed90214d65cc7523d07eb114d8fce0c0de96a2..56661276e51c8f743b2a1f5922421dfd426ef2a9
@@@ -6276,141 -5241,51 +6276,146 @@@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPT
                }
        }
  
 -      if (EX(call) >= EX(call_slots)) {
 -              call_slot *call = EX(call);
 +      if (UNEXPECTED(EX(call))) {
 +              zend_execute_data *call = EX(call);
 +              zend_op *opline = EX(func)->op_array.opcodes + op_num;
 +              int level;
 +              int do_exit;
 +
                do {
 -                      if (call->object) {
 -                              if (call->is_ctor_call) {
 -                                      if (call->is_ctor_result_used) {
 -                                              Z_DELREF_P(call->object);
 +                      /* If the exception was thrown during a function call there might be
 +                       * arguments pushed to the stack that have to be dtor'ed. */
 +
 +                      /* find the number of actually passed arguments */
 +                      level = 0;
 +                      do_exit = 0;
 +                      do {
 +                              switch (opline->opcode) {
 +                                      case ZEND_DO_FCALL:
 +                                      case ZEND_DO_ICALL:
 +                                      case ZEND_DO_UCALL:
 +                                      case ZEND_DO_FCALL_BY_NAME:
 +                                              level++;
 +                                              break;
 +                                      case ZEND_INIT_FCALL:
 +                                      case ZEND_INIT_FCALL_BY_NAME:
 +                                      case ZEND_INIT_NS_FCALL_BY_NAME:
 +                                      case ZEND_INIT_DYNAMIC_CALL:
 +                                      case ZEND_INIT_USER_CALL:
 +                                      case ZEND_INIT_METHOD_CALL:
 +                                      case ZEND_INIT_STATIC_METHOD_CALL:
 +                                      case ZEND_NEW:
 +                                              if (level == 0) {
 +                                                      ZEND_CALL_NUM_ARGS(call) = 0;
 +                                                      do_exit = 1;
 +                                              }
 +                                              level--;
 +                                              break;
 +                                      case ZEND_SEND_VAL:
 +                                      case ZEND_SEND_VAL_EX:
 +                                      case ZEND_SEND_VAR:
 +                                      case ZEND_SEND_VAR_EX:
 +                                      case ZEND_SEND_REF:
 +                                      case ZEND_SEND_VAR_NO_REF:
 +                                      case ZEND_SEND_USER:
 +                                              if (level == 0) {
 +                                                      ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
 +                                                      do_exit = 1;
 +                                              }
 +                                              break;
 +                                      case ZEND_SEND_ARRAY:
 +                                      case ZEND_SEND_UNPACK:
 +                                              if (level == 0) {
 +                                                      do_exit = 1;
 +                                              }
 +                                              break;
 +                              }
 +                              if (!do_exit) {
 +                                      opline--;
 +                              }
 +                      } while (!do_exit);
 +                      if (call->prev_execute_data) {
 +                              /* skip current call region */
 +                              level = 0;
 +                              do_exit = 0;
 +                              do {
 +                                      switch (opline->opcode) {
 +                                              case ZEND_DO_FCALL:
 +                                              case ZEND_DO_ICALL:
 +                                              case ZEND_DO_UCALL:
 +                                              case ZEND_DO_FCALL_BY_NAME:
 +                                                      level++;
 +                                                      break;
 +                                              case ZEND_INIT_FCALL:
 +                                              case ZEND_INIT_FCALL_BY_NAME:
 +                                              case ZEND_INIT_NS_FCALL_BY_NAME:
 +                                              case ZEND_INIT_DYNAMIC_CALL:
 +                                              case ZEND_INIT_USER_CALL:
 +                                              case ZEND_INIT_METHOD_CALL:
 +                                              case ZEND_INIT_STATIC_METHOD_CALL:
 +                                              case ZEND_NEW:
 +                                                      if (level == 0) {
 +                                                              do_exit = 1;
 +                                                      }
 +                                                      level--;
 +                                                      break;
 +                                      }
 +                                      opline--;
 +                              } while (!do_exit);
 +                      }
 +
 +                      zend_vm_stack_free_args(EX(call));
 +
 +                      if (Z_OBJ(call->This)) {
 +                              if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
 +                                      if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
 +                                              GC_REFCOUNT(Z_OBJ(call->This))--;
                                        }
 -                                      if (Z_REFCOUNT_P(call->object) == 1) {
 -                                              zend_object_store_ctor_failed(call->object TSRMLS_CC);
 +                                      if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
 +                                              zend_object_store_ctor_failed(Z_OBJ(call->This));
                                        }
                                }
 -                              zval_ptr_dtor(&call->object);
 +                              OBJ_RELEASE(Z_OBJ(call->This));
                        }
 -                      if (call->fbc->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
 -                              efree((char *) call->fbc->common.function_name);
 -                              efree(call->fbc);
++                      if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
++                              zend_string_release(call->func->common.function_name);
++                              efree(call->func);
+                       }
 -                      call--;
 -              } while (call >= EX(call_slots));
 -              EX(call) = NULL;
++
 +                      EX(call) = call->prev_execute_data;
 +                      zend_vm_stack_free_call_frame(call);
 +                      call = EX(call);
 +              } while (call);
        }
  
 -      for (i=0; i<EX(op_array)->last_brk_cont; i++) {
 -              if (EX(op_array)->brk_cont_array[i].start < 0) {
 +      for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
 +              if (EX(func)->op_array.brk_cont_array[i].start < 0) {
                        continue;
 -              } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
 +              } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
 -              } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
 +              } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
                        if (!catch_op_num ||
 -                          catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
 -                              zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
 +                          catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
 +                              zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
  
 -                              switch (brk_opline->opcode) {
 -                                      case ZEND_SWITCH_FREE:
 -                                              if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 -                                                      zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
 -                                              }
 -                                              break;
 -                                      case ZEND_FREE:
 -                                              if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 -                                                      zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
 +                              if (brk_opline->opcode == ZEND_FREE) {
 +                                      if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 +                                              zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
 +                                      }
 +                              } else if (brk_opline->opcode == ZEND_FE_FREE) {
 +                                      if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 +                                              zval *var = EX_VAR(brk_opline->op1.var);
 +                                              if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
 +                                                      zend_hash_iterator_del(Z_FE_ITER_P(var));
                                                }
 -                                              break;
 +                                              zval_ptr_dtor_nogc(var);
 +                                      }
 +                              } else if (brk_opline->opcode == ZEND_END_SILENCE) {
 +                                      /* restore previous error_reporting value */
 +                                      if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
 +                                              EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
 +                                      }
                                }
                        }
                }
index 621529ffa26b729f4033afc0bbc958f510f479bc,eaa22a620582aefd6e23b2f7e0cd30de5d342681..48665b81afa16d4b7e9bc8e0b231c2f4cb4fb5f0
@@@ -1417,141 -1200,51 +1417,146 @@@ static int ZEND_FASTCALL  ZEND_HANDLE_E
                }
        }
  
 -      if (EX(call) >= EX(call_slots)) {
 -              call_slot *call = EX(call);
 +      if (UNEXPECTED(EX(call))) {
 +              zend_execute_data *call = EX(call);
 +              zend_op *opline = EX(func)->op_array.opcodes + op_num;
 +              int level;
 +              int do_exit;
 +
                do {
 -                      if (call->object) {
 -                              if (call->is_ctor_call) {
 -                                      if (call->is_ctor_result_used) {
 -                                              Z_DELREF_P(call->object);
 +                      /* If the exception was thrown during a function call there might be
 +                       * arguments pushed to the stack that have to be dtor'ed. */
 +
 +                      /* find the number of actually passed arguments */
 +                      level = 0;
 +                      do_exit = 0;
 +                      do {
 +                              switch (opline->opcode) {
 +                                      case ZEND_DO_FCALL:
 +                                      case ZEND_DO_ICALL:
 +                                      case ZEND_DO_UCALL:
 +                                      case ZEND_DO_FCALL_BY_NAME:
 +                                              level++;
 +                                              break;
 +                                      case ZEND_INIT_FCALL:
 +                                      case ZEND_INIT_FCALL_BY_NAME:
 +                                      case ZEND_INIT_NS_FCALL_BY_NAME:
 +                                      case ZEND_INIT_DYNAMIC_CALL:
 +                                      case ZEND_INIT_USER_CALL:
 +                                      case ZEND_INIT_METHOD_CALL:
 +                                      case ZEND_INIT_STATIC_METHOD_CALL:
 +                                      case ZEND_NEW:
 +                                              if (level == 0) {
 +                                                      ZEND_CALL_NUM_ARGS(call) = 0;
 +                                                      do_exit = 1;
 +                                              }
 +                                              level--;
 +                                              break;
 +                                      case ZEND_SEND_VAL:
 +                                      case ZEND_SEND_VAL_EX:
 +                                      case ZEND_SEND_VAR:
 +                                      case ZEND_SEND_VAR_EX:
 +                                      case ZEND_SEND_REF:
 +                                      case ZEND_SEND_VAR_NO_REF:
 +                                      case ZEND_SEND_USER:
 +                                              if (level == 0) {
 +                                                      ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
 +                                                      do_exit = 1;
 +                                              }
 +                                              break;
 +                                      case ZEND_SEND_ARRAY:
 +                                      case ZEND_SEND_UNPACK:
 +                                              if (level == 0) {
 +                                                      do_exit = 1;
 +                                              }
 +                                              break;
 +                              }
 +                              if (!do_exit) {
 +                                      opline--;
 +                              }
 +                      } while (!do_exit);
 +                      if (call->prev_execute_data) {
 +                              /* skip current call region */
 +                              level = 0;
 +                              do_exit = 0;
 +                              do {
 +                                      switch (opline->opcode) {
 +                                              case ZEND_DO_FCALL:
 +                                              case ZEND_DO_ICALL:
 +                                              case ZEND_DO_UCALL:
 +                                              case ZEND_DO_FCALL_BY_NAME:
 +                                                      level++;
 +                                                      break;
 +                                              case ZEND_INIT_FCALL:
 +                                              case ZEND_INIT_FCALL_BY_NAME:
 +                                              case ZEND_INIT_NS_FCALL_BY_NAME:
 +                                              case ZEND_INIT_DYNAMIC_CALL:
 +                                              case ZEND_INIT_USER_CALL:
 +                                              case ZEND_INIT_METHOD_CALL:
 +                                              case ZEND_INIT_STATIC_METHOD_CALL:
 +                                              case ZEND_NEW:
 +                                                      if (level == 0) {
 +                                                              do_exit = 1;
 +                                                      }
 +                                                      level--;
 +                                                      break;
 +                                      }
 +                                      opline--;
 +                              } while (!do_exit);
 +                      }
 +
 +                      zend_vm_stack_free_args(EX(call));
 +
 +                      if (Z_OBJ(call->This)) {
 +                              if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
 +                                      if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
 +                                              GC_REFCOUNT(Z_OBJ(call->This))--;
                                        }
 -                                      if (Z_REFCOUNT_P(call->object) == 1) {
 -                                              zend_object_store_ctor_failed(call->object TSRMLS_CC);
 +                                      if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
 +                                              zend_object_store_ctor_failed(Z_OBJ(call->This));
                                        }
                                }
 -                              zval_ptr_dtor(&call->object);
 +                              OBJ_RELEASE(Z_OBJ(call->This));
                        }
 -                      if (call->fbc->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
 -                              efree((char *) call->fbc->common.function_name);
 -                              efree(call->fbc);
++                      if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
++                              zend_string_release(call->func->common.function_name);
++                              efree(call->func);
+                       }
 -                      call--;
 -              } while (call >= EX(call_slots));
 -              EX(call) = NULL;
++
 +                      EX(call) = call->prev_execute_data;
 +                      zend_vm_stack_free_call_frame(call);
 +                      call = EX(call);
 +              } while (call);
        }
  
 -      for (i=0; i<EX(op_array)->last_brk_cont; i++) {
 -              if (EX(op_array)->brk_cont_array[i].start < 0) {
 +      for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
 +              if (EX(func)->op_array.brk_cont_array[i].start < 0) {
                        continue;
 -              } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
 +              } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
 -              } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
 +              } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
                        if (!catch_op_num ||
 -                          catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
 -                              zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
 +                          catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
 +                              zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
  
 -                              switch (brk_opline->opcode) {
 -                                      case ZEND_SWITCH_FREE:
 -                                              if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 -                                                      zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
 -                                              }
 -                                              break;
 -                                      case ZEND_FREE:
 -                                              if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 -                                                      zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
 +                              if (brk_opline->opcode == ZEND_FREE) {
 +                                      if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 +                                              zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
 +                                      }
 +                              } else if (brk_opline->opcode == ZEND_FE_FREE) {
 +                                      if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
 +                                              zval *var = EX_VAR(brk_opline->op1.var);
 +                                              if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
 +                                                      zend_hash_iterator_del(Z_FE_ITER_P(var));
                                                }
 -                                              break;
 +                                              zval_ptr_dtor_nogc(var);
 +                                      }
 +                              } else if (brk_opline->opcode == ZEND_END_SILENCE) {
 +                                      /* restore previous error_reporting value */
 +                                      if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
 +                                              EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
 +                                      }
                                }
                        }
                }