com php-src: Merge branch 'PHP-5.6': Zend/zend_compile.c
| From: | Nikita Popov | Date: | Sat, 20 Sep 2014 19:58:06 +0000 |
| Subject: | com php-src: Merge branch 'PHP-5.6': Zend/zend_compile.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-81816@lists.php.net to get a copy of this message | ||
Commit: 6219a4e844e82f8eacd9ad6d24bb92739dcd6ff6
Author: Nikita Popov <nikic@php.net> Sat, 20 Sep 2014 21:58:06 +0200
Parents: 2fc1a1dce557875d029f16d58bd3d4cd22af54fb 308c0a727ec496ff551f67052b0835de3c152c11
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=6219a4e844e82f8eacd9ad6d24bb92739dcd6ff6
Log:
Merge branch 'PHP-5.6'
Conflicts:
Zend/zend_compile.c
Changed paths:
MM Zend/zend_compile.c
Diff:
diff --cc Zend/zend_compile.c
index c533759,19185df..1590225
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@@ -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));
}
/* }}} */