}
/* }}} */
-ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint32_t first_early_binding_opline) /* {{{ */
+ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t first_early_binding_opline) /* {{{ */
{
if (first_early_binding_opline != (uint32_t)-1) {
zend_bool orig_in_compilation = CG(in_compilation);
uint32_t opline_num = first_early_binding_opline;
+ void **run_time_cache;
+
+ if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
+ void *ptr;
+
+ ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
+ ptr = emalloc(op_array->cache_size + sizeof(void*));
+ ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
+ ptr = (char*)ptr + sizeof(void*);
+ ZEND_MAP_PTR_SET(op_array->run_time_cache, ptr);
+ memset(ptr, 0, op_array->cache_size);
+ }
+ run_time_cache = RUN_TIME_CACHE(op_array);
CG(in_compilation) = 1;
while (opline_num != (uint32_t)-1) {
zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1);
if (parent_ce) {
- zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv);
+ if (zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv)) {
+ /* Store in run-time cache */
+ ((void**)((char*)run_time_cache + opline->extended_value))[0] = ce;
+ }
}
}
opline_num = op_array->opcodes[opline_num].result.opline_num;
) {
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
+ opline->extended_value = zend_alloc_cache_slot();
opline->result_type = IS_UNUSED;
opline->result.opline_num = -1;
}
ZEND_API int do_bind_function(zval *lcname);
ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name);
ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array);
-ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint32_t first_early_binding_opline);
+ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t first_early_binding_opline);
void zend_do_extended_info(void);
void zend_do_extended_fcall_begin(void);
{
USE_OPLINE
zval *lcname, *zv;
+ zend_class_entry *ce;
- SAVE_OPLINE();
- lcname = RT_CONSTANT(opline, opline->op1);
- zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
-
- if (zv) {
- zend_class_entry *ce = Z_CE_P(zv);
- zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
- if (UNEXPECTED(!zv)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
- } else {
- zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+ ce = CACHED_PTR(opline->extended_value);
+ if (ce == NULL) {
+ lcname = RT_CONSTANT(opline, opline->op1);
+ zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
+ if (zv) {
+ SAVE_OPLINE();
+ ce = Z_CE_P(zv);
+ zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
+ } else {
+ zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ }
}
+ CACHE_PTR(opline->extended_value, ce);
}
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
{
USE_OPLINE
zval *lcname, *zv;
+ zend_class_entry *ce;
- SAVE_OPLINE();
- lcname = RT_CONSTANT(opline, opline->op1);
- zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
-
- if (zv) {
- zend_class_entry *ce = Z_CE_P(zv);
- zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
- if (UNEXPECTED(!zv)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
- } else {
- zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+ ce = CACHED_PTR(opline->extended_value);
+ if (ce == NULL) {
+ lcname = RT_CONSTANT(opline, opline->op1);
+ zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
+ if (zv) {
+ SAVE_OPLINE();
+ ce = Z_CE_P(zv);
+ zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
+ } else {
+ zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ }
}
+ CACHE_PTR(opline->extended_value, ce);
}
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
break;
case ZEND_DECLARE_LAMBDA_FUNCTION:
case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_CLASS_DELAYED:
opline->extended_value = cache_size;
cache_size += sizeof(void *);
break;