summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_compile.c19
-rw-r--r--Zend/zend_vm_def.h33
-rw-r--r--Zend/zend_vm_execute.h233
-rw-r--r--ext/opcache/Optimizer/compact_literals.c5
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c1
-rw-r--r--ext/spl/php_spl.c4
6 files changed, 206 insertions, 89 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 988a42b496..9847987470 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -514,7 +514,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
opline->result_type |= EXT_TYPE_UNUSED;
}
} else {
- while (opline>CG(active_op_array)->opcodes) {
+ while (opline >= CG(active_op_array)->opcodes) {
if (opline->opcode == ZEND_FETCH_LIST &&
opline->op1_type == IS_VAR &&
opline->op1.var == op1->u.op.var) {
@@ -2937,10 +2937,23 @@ void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
zend_op *opline;
uint32_t opnum;
- zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ if (zend_is_const_default_class_ref(class_ast)) {
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
+ } else {
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
+ }
opnum = get_next_op_number(CG(active_op_array));
- zend_emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC);
+ opline = zend_emit_op(result, ZEND_NEW, NULL, NULL TSRMLS_CC);
+
+ if (class_node.op_type == IS_CONST) {
+ opline->op1_type = IS_CONST;
+ opline->op1.constant = zend_add_class_name_literal(
+ CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op1, &class_node);
+ }
zend_compile_call_common(&ctor_result, args_ast, NULL TSRMLS_CC);
zend_do_free(&ctor_result TSRMLS_CC);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 42ad32bbb6..9171feaadd 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3635,23 +3635,38 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
+ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
{
USE_OPLINE
zval object_zval;
zend_function *constructor;
+ zend_class_entry *ce;
SAVE_OPLINE();
- if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
- if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
- } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
+ if (OP1_TYPE == IS_CONST) {
+ if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+ if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
} else {
- zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
+ zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
}
}
- object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var)));
+ object_init_ex(&object_zval, ce);
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
if (constructor == NULL) {
@@ -3670,7 +3685,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
constructor,
opline->extended_value,
- Z_CE_P(EX_VAR(opline->op1.var)),
+ ce,
Z_OBJ(object_zval),
EX(call) TSRMLS_CC);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index f2dae2acba..1bbeb4960d 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1023,57 +1023,6 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zval object_zval;
- zend_function *constructor;
-
- SAVE_OPLINE();
- if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
- if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
- } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
- } else {
- zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val);
- }
- }
- object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var)));
- constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
-
- if (constructor == NULL) {
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
- } else {
- zval_ptr_dtor(&object_zval);
- }
- ZEND_VM_JMP(opline->op2.jmp_addr);
- } else {
- /* We are not handling overloaded classes right now */
- EX(call) = zend_vm_stack_push_call_frame(
- VM_FRAME_INFO(
- VM_FRAME_NESTED_FUNCTION,
- RETURN_VALUE_USED(opline) ?
- ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
- constructor,
- opline->extended_value,
- Z_CE_P(EX_VAR(opline->op1.var)),
- Z_OBJ(object_zval),
- EX(call) TSRMLS_CC);
-
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
- EX(call)->return_value = EX_VAR(opline->result.var);
- } else {
- EX(call)->return_value = NULL;
- }
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
- }
-}
-
static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -2769,6 +2718,72 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval object_zval;
+ zend_function *constructor;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+ if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
+ } else {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
+ }
+ }
+ object_init_ex(&object_zval, ce);
+ constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
+
+ if (constructor == NULL) {
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
+ } else {
+ zval_ptr_dtor(&object_zval);
+ }
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ } else {
+ /* We are not handling overloaded classes right now */
+ EX(call) = zend_vm_stack_push_call_frame(
+ VM_FRAME_INFO(
+ VM_FRAME_NESTED_FUNCTION,
+ RETURN_VALUE_USED(opline) ?
+ ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
+ constructor,
+ opline->extended_value,
+ ce,
+ Z_OBJ(object_zval),
+ EX(call) TSRMLS_CC);
+
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
+ EX(call)->return_value = EX_VAR(opline->result.var);
+ } else {
+ EX(call)->return_value = NULL;
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+}
+
static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -16302,6 +16317,72 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval object_zval;
+ zend_function *constructor;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+ if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
+ } else {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
+ }
+ }
+ object_init_ex(&object_zval, ce);
+ constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC);
+
+ if (constructor == NULL) {
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
+ } else {
+ zval_ptr_dtor(&object_zval);
+ }
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ } else {
+ /* We are not handling overloaded classes right now */
+ EX(call) = zend_vm_stack_push_call_frame(
+ VM_FRAME_INFO(
+ VM_FRAME_NESTED_FUNCTION,
+ RETURN_VALUE_USED(opline) ?
+ ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)),
+ constructor,
+ opline->extended_value,
+ ce,
+ Z_OBJ(object_zval),
+ EX(call) TSRMLS_CC);
+
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
+ EX(call)->return_value = EX_VAR(opline->result.var);
+ } else {
+ EX(call)->return_value = NULL;
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+}
+
static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -45345,31 +45426,31 @@ void zend_init_opcodes_handlers(void)
ZEND_SEND_REF_SPEC_CV_HANDLER,
ZEND_SEND_REF_SPEC_CV_HANDLER,
ZEND_SEND_REF_SPEC_CV_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
- ZEND_NEW_SPEC_HANDLER,
+ ZEND_NEW_SPEC_CONST_HANDLER,
+ ZEND_NEW_SPEC_CONST_HANDLER,
+ ZEND_NEW_SPEC_CONST_HANDLER,
+ ZEND_NEW_SPEC_CONST_HANDLER,
+ ZEND_NEW_SPEC_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NEW_SPEC_VAR_HANDLER,
+ ZEND_NEW_SPEC_VAR_HANDLER,
+ ZEND_NEW_SPEC_VAR_HANDLER,
+ ZEND_NEW_SPEC_VAR_HANDLER,
+ ZEND_NEW_SPEC_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 79f3c04352..8fb5a9b0c9 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -232,6 +232,11 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
}
break;
+ case ZEND_NEW:
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+ }
+ break;
case ZEND_ASSIGN_OBJ:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index fb40349d27..1a6d0b675a 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -126,6 +126,7 @@ void zend_optimizer_update_op1_const(zend_op_array *op_array,
case ZEND_CATCH:
case ZEND_FETCH_CONSTANT:
case ZEND_DEFINED:
+ case ZEND_NEW:
opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 44078733d6..1de8e021dd 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -351,7 +351,9 @@ PHP_FUNCTION(spl_autoload)
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
ex = ex->prev_execute_data;
}
- if (ex && ex->opline->opcode != ZEND_FETCH_CLASS) {
+ if (ex &&
+ ex->opline->opcode != ZEND_FETCH_CLASS &&
+ ex->opline->opcode != ZEND_NEW) {
zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Class %s could not be loaded", class_name->val);
} else {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be loaded", class_name->val);