]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6'
authorNikita Popov <nikic@php.net>
Sat, 20 Sep 2014 19:58:06 +0000 (21:58 +0200)
committerNikita Popov <nikic@php.net>
Sat, 20 Sep 2014 19:58:06 +0000 (21:58 +0200)
Conflicts:
Zend/zend_compile.c

1  2 
Zend/zend_compile.c

index c5337595c5c3acdf6fb2e783ee010558b2a5fd02,19185dfb70d6c44e41f086899d3d875ee76f8dec..15902256db335c26543b08191d8bdb035a22968b
@@@ -3380,99 -4737,131 +3380,103 @@@ void zend_compile_for(zend_ast *ast TSR
  }
  /* }}} */
  
 -void zend_do_early_binding(TSRMLS_D) /* {{{ */
 +void zend_compile_foreach(zend_ast *ast TSRMLS_DC) /* {{{ */
  {
 -      zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
 -      HashTable *table;
 +      zend_ast *expr_ast = ast->child[0];
 +      zend_ast *value_ast = ast->child[1];
 +      zend_ast *key_ast = ast->child[2];
 +      zend_ast *stmt_ast = ast->child[3];
 +      zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
 +      zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast)
 +              && zend_can_write_to_variable(expr_ast);
  
 -      while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
 -              opline--;
 -      }
 +      znode expr_node, reset_node, value_node, key_node, dummy_node;
 +      zend_op *opline;
 +      uint32_t opnum_reset, opnum_fetch;
  
 -      switch (opline->opcode) {
 -              case ZEND_DECLARE_FUNCTION:
 -                      if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
 -                              return;
 -                      }
 -                      table = CG(function_table);
 -                      break;
 -              case ZEND_DECLARE_CLASS:
 -                      if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
 -                              return;
 -                      }
 -                      table = CG(class_table);
 -                      break;
 -              case ZEND_DECLARE_INHERITED_CLASS:
 -                      {
 -                              zend_op *fetch_class_opline = opline-1;
 -                              zval *parent_name;
 -                              zend_class_entry **pce;
 +      if (key_ast) {
 +              if (key_ast->kind == ZEND_AST_REF) {
 +                      zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
 +              }
 +              if (key_ast->kind == ZEND_AST_LIST) {
 +                      zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
 +              }
 +      }
  
 -                              parent_name = &CONSTANT(fetch_class_opline->op2.constant);
 -                              if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
 -                                  ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
 -                                   ((*pce)->type == ZEND_INTERNAL_CLASS))) {
 -                                  if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
 -                                              zend_uint *opline_num = &CG(active_op_array)->early_binding;
 +      if (by_ref) {
 +              value_ast = value_ast->child[0];
 +      }
  
 -                                              while (*opline_num != -1) {
 -                                                      opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
 -                                              }
 -                                              *opline_num = opline - CG(active_op_array)->opcodes;
 -                                              opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
 -                                              opline->result_type = IS_UNUSED;
 -                                              opline->result.opline_num = -1;
 -                                      }
 -                                      return;
 -                              }
 -                              if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
 -                                      return;
 -                              }
 -                              /* clear unnecessary ZEND_FETCH_CLASS opcode */
 -                              zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
 -                              MAKE_NOP(fetch_class_opline);
 +      if (by_ref && is_variable) {
 +              zend_compile_var(&expr_node, expr_ast, BP_VAR_W TSRMLS_CC);
 +      } else {
 +              zend_compile_expr(&expr_node, expr_ast TSRMLS_CC);
 +      }
  
 -                              table = CG(class_table);
 -                              break;
 -                      }
 -              case ZEND_VERIFY_ABSTRACT_CLASS:
 -              case ZEND_ADD_INTERFACE:
 -              case ZEND_ADD_TRAIT:
 -              case ZEND_BIND_TRAITS:
 -                      /* We currently don't early-bind classes that implement interfaces */
 -                      /* Classes with traits are handled exactly the same, no early-bind here */
 -                      return;
 -              default:
 -                      zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
 -                      return;
++      if (by_ref) {
++              zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W TSRMLS_CC);
+       }
 -      zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
 -      zend_del_literal(CG(active_op_array), opline->op1.constant);
 -      zend_del_literal(CG(active_op_array), opline->op2.constant);
 -      MAKE_NOP(opline);
 -}
 -/* }}} */
 +      opnum_reset = get_next_op_number(CG(active_op_array));
 +      opline = zend_emit_op(&reset_node, ZEND_FE_RESET, &expr_node, NULL TSRMLS_CC);
 +      if (by_ref && is_variable) {
 +              opline->extended_value = ZEND_FE_FETCH_BYREF;
 +      }
  
 -ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
 -{
 -      if (op_array->early_binding != -1) {
 -              zend_bool orig_in_compilation = CG(in_compilation);
 -              zend_uint opline_num = op_array->early_binding;
 -              zend_class_entry **pce;
 +      zend_stack_push(&CG(loop_var_stack), &reset_node);
  
 -              CG(in_compilation) = 1;
 -              while (opline_num != -1) {
 -                      if (zend_lookup_class(Z_STRVAL_P(op_array->opcodes[opline_num-1].op2.zv), Z_STRLEN_P(op_array->opcodes[opline_num-1].op2.zv), &pce TSRMLS_CC) == SUCCESS) {
 -                              do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
 -                      }
 -                      opline_num = op_array->opcodes[opline_num].result.opline_num;
 -              }
 -              CG(in_compilation) = orig_in_compilation;
 +      opnum_fetch = get_next_op_number(CG(active_op_array));
 +      opline = zend_emit_op(&value_node, ZEND_FE_FETCH, &reset_node, NULL TSRMLS_CC);
 +      if (by_ref) {
 +              opline->extended_value |= ZEND_FE_FETCH_BYREF;
 +      }
 +      if (key_ast) {
 +              opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
        }
 -}
 -/* }}} */
  
 -void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
 -{
 -      int next_op_number = get_next_op_number(CG(active_op_array));
 -      zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 +      opline = zend_emit_op(NULL, ZEND_OP_DATA, NULL, NULL TSRMLS_CC);
 +
 +      /* Allocate enough space to keep HashPointer on VM stack */
 +      opline->op1_type = IS_TMP_VAR;
 +      opline->op1.var = get_temporary_variable(CG(active_op_array));
 +      if (sizeof(HashPointer) > sizeof(zval)) {
 +              /* Make sure 1 zval is enough for HashPointer (2 must be enough) */
 +              get_temporary_variable(CG(active_op_array));
 +      }
  
 -      opline->opcode = ZEND_JMPNZ_EX;
 -      if (expr1->op_type == IS_TMP_VAR) {
 -              SET_NODE(opline->result, expr1);
 +      if (key_ast) {
 +              zend_make_tmp_result(&key_node, opline TSRMLS_CC);
 +      }
 +
 +      if (value_ast->attr == ZEND_AST_LIST) {
 +              zend_compile_list_assign(&dummy_node, value_ast, &value_node TSRMLS_CC);
 +              zend_do_free(&dummy_node TSRMLS_CC);
 +      } else if (by_ref) {
 +              zend_emit_assign_ref_znode(value_ast, &value_node TSRMLS_CC);
        } else {
 -              opline->result.var = get_temporary_variable(CG(active_op_array));
 -              opline->result_type = IS_TMP_VAR;
 +              zend_emit_assign_znode(value_ast, &value_node TSRMLS_CC);
        }
 -      SET_NODE(opline->op1, expr1);
 -      SET_UNUSED(opline->op2);
  
 -      op_token->u.op.opline_num = next_op_number;
 +      if (key_ast) {
 +              zend_emit_assign_znode(key_ast, &key_node TSRMLS_CC);
 +      }
  
 -      GET_NODE(expr1, opline->result);
 -}
 -/* }}} */
 +      zend_begin_loop(TSRMLS_C);
  
 -void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
 -{
 -      zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 +      zend_compile_stmt(stmt_ast TSRMLS_CC);
  
 -      *result = *expr1; /* we saved the original result in expr1 */
 -      opline->opcode = ZEND_BOOL;
 -      SET_NODE(opline->result, result);
 -      SET_NODE(opline->op1, expr2);
 -      SET_UNUSED(opline->op2);
 +      zend_emit_jump(opnum_fetch TSRMLS_CC);
 +
 +      opline = &CG(active_op_array)->opcodes[opnum_reset];
 +      opline->op2.opline_num = get_next_op_number(CG(active_op_array));
 +
 +      opline = &CG(active_op_array)->opcodes[opnum_fetch];
 +      opline->op2.opline_num = get_next_op_number(CG(active_op_array));
 +
 +      zend_end_loop(opnum_fetch, 1 TSRMLS_CC);
  
 -      CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
 +      generate_free_loop_var(&reset_node TSRMLS_CC);
 +      zend_stack_del_top(&CG(loop_var_stack));
  }
  /* }}} */