}
/* }}} */
-static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */
+static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, uint32_t by_ref) /* {{{ */
{
znode var_node;
zend_op *opline;
}
CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
}
- zend_hash_update(CG(active_op_array)->static_variables, var_name, value);
+ value = zend_hash_update(CG(active_op_array)->static_variables, var_name, value);
if (zend_string_equals_literal(var_name, "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node);
opline->op1_type = IS_CV;
opline->op1.var = lookup_cv(CG(active_op_array), var_name);
- opline->extended_value = by_ref;
+ opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | by_ref;
}
/* }}} */
ZVAL_NULL(&value_zv);
}
- zend_compile_static_var_common(var_ast, &value_zv, 1);
+ zend_compile_static_var_common(var_ast, &value_zv, ZEND_BIND_REF);
}
/* }}} */
}
/* }}} */
-static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* {{{ */
+static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array, zend_ast *uses_ast) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(uses_ast);
uint32_t i;
+ if (!list->children) {
+ return;
+ }
+
+ if (!op_array->static_variables) {
+ op_array->static_variables = zend_new_array(8);
+ }
+
+ if (GC_REFCOUNT(op_array->static_variables) > 1) {
+ if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
+ GC_DELREF(op_array->static_variables);
+ }
+ op_array->static_variables = zend_array_dup(op_array->static_variables);
+ }
+
for (i = 0; i < list->children; ++i) {
zend_ast *var_name_ast = list->child[i];
zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_name_ast));
- zend_bool by_ref = var_name_ast->attr;
+ uint32_t by_ref = var_name_ast->attr;
zend_op *opline;
+ zval *value;
if (zend_string_equals_literal(var_name, "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
}
+ value = zend_hash_add(op_array->static_variables, var_name, &EG(uninitialized_zval));
+ if (!value) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use variable $%s twice", ZSTR_VAL(var_name));
+ }
+
opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
opline->op2_type = IS_CV;
opline->op2.var = lookup_cv(CG(active_op_array), var_name);
- opline->extended_value = by_ref;
+ opline->extended_value = (uint32_t)((char*)value - (char*)op_array->static_variables->arData) | by_ref;
}
}
/* }}} */
for (i = 0; i < list->children; ++i) {
zend_ast *var_ast = list->child[i];
zend_string *var_name = zend_ast_get_str(var_ast);
- zend_bool by_ref = var_ast->attr;
+ uint32_t by_ref = var_ast->attr;
zval zv;
ZVAL_NULL(&zv);
- if (op_array->static_variables
- && zend_hash_exists(op_array->static_variables, var_name)) {
- zend_error_noreturn(E_COMPILE_ERROR,
- "Cannot use variable $%s twice", ZSTR_VAL(var_name));
- }
-
{
int i;
for (i = 0; i < op_array->last_var; i++) {
} else {
zend_begin_func_decl(result, op_array, decl);
if (uses_ast) {
- zend_compile_closure_binding(result, uses_ast);
+ zend_compile_closure_binding(result, op_array, uses_ast);
}
}
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *closure, *var;
- zend_string *var_name;
closure = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (opline->extended_value) {
+ if (opline->extended_value & ZEND_BIND_REF) {
/* By-ref binding */
var = GET_OP2_ZVAL_PTR(BP_VAR_W);
if (Z_ISREF_P(var)) {
Z_TRY_ADDREF_P(var);
}
- var_name = CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var));
- zend_closure_bind_var(closure, var_name, var);
+ zend_closure_bind_var_ex(closure, (opline->extended_value & ~ZEND_BIND_REF), var);
ZEND_VM_NEXT_OPCODE();
}
}
varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
- value = zend_hash_find_ex(ht, Z_STR_P(varname), 1);
+ value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF));
- if (opline->extended_value) {
+ if (opline->extended_value & ZEND_BIND_REF) {
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
SAVE_OPLINE();
if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) {
USE_OPLINE
zend_free_op free_op1;
zval *closure, *var;
- zend_string *var_name;
closure = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC);
- if (opline->extended_value) {
+ if (opline->extended_value & ZEND_BIND_REF) {
/* By-ref binding */
var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC);
if (Z_ISREF_P(var)) {
Z_TRY_ADDREF_P(var);
}
- var_name = CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var));
- zend_closure_bind_var(closure, var_name, var);
+ zend_closure_bind_var_ex(closure, (opline->extended_value & ~ZEND_BIND_REF), var);
ZEND_VM_NEXT_OPCODE();
}
}
varname = RT_CONSTANT(opline, opline->op2);
- value = zend_hash_find_ex(ht, Z_STR_P(varname), 1);
+ value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF));
- if (opline->extended_value) {
+ if (opline->extended_value & ZEND_BIND_REF) {
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
SAVE_OPLINE();
if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) {