diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 6701ca49028b5..935ca251316e6 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2284,15 +2284,11 @@ ZEND_API void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_D { void *p; - HANDLE_BLOCK_INTERRUPTIONS(); - p = _safe_emalloc(nmemb, size, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memset(p, 0, size * nmemb); - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2301,16 +2297,12 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_ size_t length; char *p; - HANDLE_BLOCK_INTERRUPTIONS(); - length = strlen(s)+1; p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memcpy(p, s, length); - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2318,16 +2310,12 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI { char *p; - HANDLE_BLOCK_INTERRUPTIONS(); - p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memcpy(p, s, length); p[length] = 0; - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2336,18 +2324,14 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) { char *p; - HANDLE_BLOCK_INTERRUPTIONS(); - p = (char *) malloc(length+1); if (UNEXPECTED(p == NULL)) { - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } if (length) { memcpy(p, s, length); } p[length] = 0; - HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 59e585e35b06e..26b7c18a2306b 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2035,13 +2035,25 @@ static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data } /* }}} */ +#define ZEND_VM_CHECK_INTERRUPT() do { \ + if (UNEXPECTED(EG(vm_interrupt))) { \ + ZEND_VM_INTERRUPT(); \ + } \ + } while (0) + #define ZEND_VM_NEXT_OPCODE() \ CHECK_SYMBOL_TABLES() \ ZEND_VM_INC_OPCODE(); \ ZEND_VM_CONTINUE() +#define ZEND_VM_NEXT_OPCODE_EX(new_op) \ + CHECK_SYMBOL_TABLES() \ + OPLINE = new_op; \ + ZEND_VM_CONTINUE() + #define ZEND_VM_SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ + ZEND_VM_CHECK_INTERRUPT(); \ OPLINE = new_op #define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \ @@ -2050,6 +2062,7 @@ static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data #define ZEND_VM_JMP(new_op) \ if (EXPECTED(!EG(exception))) { \ ZEND_VM_SET_OPCODE(new_op); \ + ZEND_VM_CHECK_INTERRUPT(); \ } else { \ LOAD_OPLINE(); \ } \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index c3bd69a5b1e1d..298edd81d1226 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -159,6 +159,8 @@ void init_executor(void) /* {{{ */ zend_hash_init(&EG(included_files), 8, NULL, NULL, 0); + EG(vm_interrupt) = 0; + EG(timed_out) = 0; EG(ticks_count) = 0; ZVAL_UNDEF(&EG(user_error_handler)); @@ -172,9 +174,6 @@ void init_executor(void) /* {{{ */ zend_objects_store_init(&EG(objects_store), 1024); EG(full_tables_cleanup) = 0; -#ifdef ZEND_WIN32 - EG(timed_out) = 0; -#endif EG(exception) = NULL; EG(prev_exception) = NULL; @@ -1160,21 +1159,8 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, ZEND_API void zend_timeout(int dummy) /* {{{ */ { - - if (zend_on_timeout) { -#ifdef ZEND_SIGNALS - /* - We got here because we got a timeout signal, so we are in a signal handler - at this point. However, we want to be able to timeout any user-supplied - shutdown functions, so pretend we are not in a signal handler while we are - calling these - */ - SIGG(running) = 0; -#endif - zend_on_timeout(EG(timeout_seconds)); - } - - zend_error(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); + EG(timed_out) = 1; + EG(vm_interrupt) = 1; } /* }}} */ @@ -1189,8 +1175,9 @@ VOID CALLBACK tq_timer_cb(PVOID arg, BOOLEAN timed_out) return; } - php_timed_out = (zend_bool *)arg; - *php_timed_out = 1; + php_timed_out = (zend_interrupt *)arg; + php_timed_out[1] = 1; + php_timed_out[0] = 1; } #endif @@ -1223,7 +1210,7 @@ void zend_set_timeout(zend_long seconds, int reset_signals) /* {{{ */ } /* XXX passing NULL means the default timer queue provided by the system is used */ - if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(timed_out), seconds*1000, 0, WT_EXECUTEONLYONCE)) { + if (!CreateTimerQueueTimer(&tq_timer, NULL, (WAITORTIMERCALLBACK)tq_timer_cb, (VOID*)&EG(vm_interrupt), seconds*1000, 0, WT_EXECUTEONLYONCE)) { EG(timed_out) = 0; tq_timer = NULL; zend_error(E_ERROR, "Could not queue new timer"); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index afd668afb8715..d5260bba93789 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -179,6 +179,9 @@ struct _zend_executor_globals { zend_long precision; + zend_bool vm_interrupt; + zend_bool timed_out; + int ticks_count; HashTable *in_autoload; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 8a9a032e1673b..69d535fa22315 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -178,10 +178,8 @@ static void zend_hash_packed_grow(HashTable *ht) if (ht->nTableSize >= HT_MAX_SIZE) { zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket)); } - HANDLE_BLOCK_INTERRUPTIONS(); ht->nTableSize += ht->nTableSize; zend_hash_realloc(ht, ht->nTableSize * sizeof(Bucket)); - HANDLE_UNBLOCK_INTERRUPTIONS(); } ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed) @@ -195,24 +193,20 @@ ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed) ZEND_API void zend_hash_packed_to_hash(HashTable *ht) { HT_ASSERT(GC_REFCOUNT(ht) == 1); - HANDLE_BLOCK_INTERRUPTIONS(); ht->u.flags &= ~HASH_FLAG_PACKED; ht->nTableMask = ht->nTableSize - 1; zend_hash_realloc(ht, ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t))); ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize); zend_hash_rehash(ht); - HANDLE_UNBLOCK_INTERRUPTIONS(); } ZEND_API void zend_hash_to_packed(HashTable *ht) { HT_ASSERT(GC_REFCOUNT(ht) == 1); - HANDLE_BLOCK_INTERRUPTIONS(); ht->u.flags |= HASH_FLAG_PACKED; ht->nTableMask = 0; zend_hash_realloc(ht, ht->nTableSize * sizeof(Bucket)); ht->arHash = (uint32_t*)&uninitialized_bucket; - HANDLE_UNBLOCK_INTERRUPTIONS(); } ZEND_API void _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC) @@ -236,21 +230,17 @@ ZEND_API void zend_hash_extend(HashTable *ht, uint32_t nSize, zend_bool packed) if (packed) { ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED); if (nSize > ht->nTableSize) { - HANDLE_BLOCK_INTERRUPTIONS(); ht->nTableSize = zend_hash_check_size(nSize); zend_hash_realloc(ht, ht->nTableSize * sizeof(Bucket)); - HANDLE_UNBLOCK_INTERRUPTIONS(); } } else { ZEND_ASSERT(!(ht->u.flags & HASH_FLAG_PACKED)); if (nSize > ht->nTableSize) { - HANDLE_BLOCK_INTERRUPTIONS(); ht->nTableSize = zend_hash_check_size(nSize); zend_hash_realloc(ht, ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t))); ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize); ht->nTableMask = ht->nTableSize - 1; zend_hash_rehash(ht); - HANDLE_UNBLOCK_INTERRUPTIONS(); } } } @@ -492,12 +482,10 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) { data = Z_INDIRECT_P(data); } - HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pDestructor) { ht->pDestructor(data); } ZVAL_COPY_VALUE(data, pData); - HANDLE_UNBLOCK_INTERRUPTIONS(); return data; } } @@ -505,7 +493,6 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ add_to_hash: - HANDLE_BLOCK_INTERRUPTIONS(); idx = ht->nNumUsed++; ht->nNumOfElements++; if (ht->nInternalPointer == INVALID_IDX) { @@ -520,7 +507,6 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s nIndex = h & ht->nTableMask; Z_NEXT(p->val) = ht->arHash[nIndex]; ht->arHash[nIndex] = idx; - HANDLE_UNBLOCK_INTERRUPTIONS(); return &p->val; } @@ -662,7 +648,6 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, } add_to_packed: - HANDLE_BLOCK_INTERRUPTIONS(); /* incremental initialization of empty Buckets */ if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) { ht->nNumUsed = h + 1; @@ -688,8 +673,6 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, p->key = NULL; ZVAL_COPY_VALUE(&p->val, pData); - HANDLE_UNBLOCK_INTERRUPTIONS(); - return &p->val; convert_to_hash: @@ -701,12 +684,10 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, return NULL; } ZEND_ASSERT(&p->val != pData); - HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pDestructor) { ht->pDestructor(&p->val); } ZVAL_COPY_VALUE(&p->val, pData); - HANDLE_UNBLOCK_INTERRUPTIONS(); if ((zend_long)h >= (zend_long)ht->nNextFreeElement) { ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; } @@ -717,7 +698,6 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ add_to_hash: - HANDLE_BLOCK_INTERRUPTIONS(); idx = ht->nNumUsed++; ht->nNumOfElements++; if (ht->nInternalPointer == INVALID_IDX) { @@ -734,7 +714,6 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, ZVAL_COPY_VALUE(&p->val, pData); Z_NEXT(p->val) = ht->arHash[nIndex]; ht->arHash[nIndex] = idx; - HANDLE_UNBLOCK_INTERRUPTIONS(); return &p->val; } @@ -776,17 +755,13 @@ static void zend_hash_do_resize(HashTable *ht) HT_ASSERT(GC_REFCOUNT(ht) == 1); if (ht->nNumUsed > ht->nNumOfElements) { - HANDLE_BLOCK_INTERRUPTIONS(); zend_hash_rehash(ht); - HANDLE_UNBLOCK_INTERRUPTIONS(); } else if (ht->nTableSize < HT_MAX_SIZE) { /* Let's double the table size */ - HANDLE_BLOCK_INTERRUPTIONS(); ht->nTableSize += ht->nTableSize; zend_hash_realloc(ht, ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t))); ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize); ht->nTableMask = ht->nTableSize - 1; zend_hash_rehash(ht); - HANDLE_UNBLOCK_INTERRUPTIONS(); } else { zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket)); } @@ -850,7 +825,6 @@ ZEND_API int zend_hash_rehash(HashTable *ht) static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev) { - HANDLE_BLOCK_INTERRUPTIONS(); if (!(ht->u.flags & HASH_FLAG_PACKED)) { if (prev) { Z_NEXT(prev->val) = Z_NEXT(p->val); @@ -892,7 +866,6 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, } else { ZVAL_UNDEF(&p->val); } - HANDLE_UNBLOCK_INTERRUPTIONS(); } static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p) @@ -2002,7 +1975,6 @@ ZEND_API int zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t c (swap_func_t)(renumber? zend_hash_bucket_renum_swap : ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap))); - HANDLE_BLOCK_INTERRUPTIONS(); ht->nNumUsed = i; ht->nInternalPointer = 0; @@ -2033,8 +2005,6 @@ ZEND_API int zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t c } } - HANDLE_UNBLOCK_INTERRUPTIONS(); - return SUCCESS; } diff --git a/Zend/zend_string.c b/Zend/zend_string.c index 634e2c810487c..c4ccf75d72b90 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -111,19 +111,15 @@ static zend_string *zend_new_interned_string_int(zend_string *str) uint32_t *h = (uint32_t *) perealloc_recoverable(CG(interned_strings).arHash, (CG(interned_strings).nTableSize << 1) * sizeof(uint32_t), 1); if (d && h) { - HANDLE_BLOCK_INTERRUPTIONS(); CG(interned_strings).arData = d; CG(interned_strings).arHash = h; CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1); CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; zend_hash_rehash(&CG(interned_strings)); - HANDLE_UNBLOCK_INTERRUPTIONS(); } } } - HANDLE_BLOCK_INTERRUPTIONS(); - idx = CG(interned_strings).nNumUsed++; CG(interned_strings).nNumOfElements++; p = CG(interned_strings).arData + idx; @@ -135,8 +131,6 @@ static zend_string *zend_new_interned_string_int(zend_string *str) Z_NEXT(p->val) = CG(interned_strings).arHash[nIndex]; CG(interned_strings).arHash[nIndex] = idx; - HANDLE_UNBLOCK_INTERRUPTIONS(); - return str; #else return str; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9714cf7ad3c53..496c865d57d55 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -25,6 +25,21 @@ * php zend_vm_gen.php */ +ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY) +{ + // TODO: use atomic instruction ??? + if (EG(vm_interrupt)) { + EG(vm_interrupt) = 0; + if (EG(timed_out)) { + if (zend_on_timeout) { + zend_on_timeout(EG(timeout_seconds)); + } + zend_error(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); + } + } + ZEND_VM_CONTINUE(); +} + ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE @@ -2094,7 +2109,7 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY) val = GET_OP1_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { if (OP1_TYPE == IS_CV) { @@ -2133,7 +2148,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY) if (OP1_TYPE == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -2195,7 +2210,7 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY) if (Z_TYPE_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -2241,7 +2256,7 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY) if (OP1_TYPE == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 66cbf0453ab49..841c3d8eb50d9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -329,10 +329,11 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend #define ZEND_VM_RETURN() return -1 #define ZEND_VM_ENTER() return 1 #define ZEND_VM_LEAVE() return 2 +#define ZEND_VM_INTERRUPT() return zend_interrupt_helper_SPEC(execute_data) #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data + ZEND_API void execute_ex(zend_execute_data *execute_data) { DCL_OPLINE @@ -343,12 +344,6 @@ ZEND_API void execute_ex(zend_execute_data *execute_data) while (1) { int ret; -#ifdef ZEND_WIN32 - if (EG(timed_out)) { - zend_timeout(0); - } -#endif - if (UNEXPECTED((ret = OPLINE->handler(execute_data)) != 0)) { if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); @@ -381,6 +376,21 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) zend_execute_ex(execute_data); } +static int ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +{ + // TODO: use atomic instruction ??? + if (EG(vm_interrupt)) { + EG(vm_interrupt) = 0; + if (EG(timed_out)) { + if (zend_on_timeout) { + zend_on_timeout(EG(timeout_seconds)); + } + zend_error(E_ERROR, "Maximum execution time of %pd second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); + } + } + ZEND_VM_CONTINUE(); +} + static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { zend_execute_data *old_execute_data; @@ -2581,7 +2591,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) val = EX_CONSTANT(opline->op1); if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { if (IS_CONST == IS_CV) { @@ -2620,7 +2630,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CONST == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -2682,7 +2692,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR if (Z_TYPE_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -2728,7 +2738,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A if (IS_CONST == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -24793,7 +24803,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { if (IS_CV == IS_CV) { @@ -24832,7 +24842,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_CV == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -24894,7 +24904,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (Z_TYPE_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -24940,7 +24950,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CV == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -34830,7 +34840,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (Z_TYPE_P(val) == IS_TRUE) { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { if ((IS_TMP_VAR|IS_VAR) == IS_CV) { @@ -34869,7 +34879,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if ((IS_TMP_VAR|IS_VAR) == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } @@ -34931,7 +34941,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_A if (Z_TYPE_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) { ZVAL_FALSE(EX_VAR(opline->result.var)); @@ -34977,7 +34987,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ if ((IS_TMP_VAR|IS_VAR) == IS_CV) { ZEND_VM_NEXT_OPCODE(); } else { - ZEND_VM_SET_OPCODE(opline + 1); + ZEND_VM_NEXT_OPCODE_EX(opline + 1); ZEND_VM_CONTINUE(); } } diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 5a5c6a9965689..98370a3498554 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -12,12 +12,6 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data) while (1) { {%ZEND_VM_CONTINUE_LABEL%} -#ifdef ZEND_WIN32 - if (EG(timed_out)) { - zend_timeout(0); - } -#endif - {%ZEND_VM_DISPATCH%} { {%INTERNAL_EXECUTOR%} } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 65b1c72c067df..97db4a422b55f 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -979,9 +979,14 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return -1\n"); out($f,"#define ZEND_VM_ENTER() return 1\n"); out($f,"#define ZEND_VM_LEAVE() return 2\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + if (ZEND_VM_SPEC) { + out($f,"#define ZEND_VM_INTERRUPT() return zend_interrupt_helper_SPEC(execute_data)\n"); + } else { + out($f,"#define ZEND_VM_INTERRUPT() return zend_interrupt_helper(execute_data)\n"); + } + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data\n"); + out($f,"\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); @@ -1005,9 +1010,14 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + if (ZEND_VM_SPEC) { + out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper_SPEC\n"); + } else { + out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper\n"); + } + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data\n"); + out($f,"\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); @@ -1037,9 +1047,14 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + if (ZEND_VM_SPEC) { + out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper_SPEC\n"); + } else { + out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper\n"); + } + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data\n"); + out($f,"\n"); break; } break; @@ -1478,9 +1493,10 @@ function gen_vm($def, $skel) { out($f,"#define ZEND_VM_RETURN() return -1\n"); out($f,"#define ZEND_VM_ENTER() return 1\n"); out($f,"#define ZEND_VM_LEAVE() return 2\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -\n"); + out($f,"#define ZEND_VM_INTERRUPT() return zend_interrupt_helper(execute_data)\n"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data\n"); + out($f,"\n"); } foreach ($export as $dsk) { list($kind, $func, $name) = $dsk; diff --git a/ext/standard/array.c b/ext/standard/array.c index e3f2a5d7cb702..9d860a7f56b6c 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1933,7 +1933,6 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ } } } - HANDLE_BLOCK_INTERRUPTIONS(); hash->nNumUsed = n_elems; hash->nInternalPointer = 0; @@ -1949,7 +1948,6 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ if (!(hash->u.flags & HASH_FLAG_PACKED)) { zend_hash_to_packed(hash); } - HANDLE_UNBLOCK_INTERRUPTIONS(); } /* }}} */ @@ -4520,7 +4518,6 @@ PHP_FUNCTION(array_multisort) zend_qsort(indirect, array_size, sizeof(Bucket *), php_multisort_compare, (swap_func_t)array_bucket_p_sawp); /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */ - HANDLE_BLOCK_INTERRUPTIONS(); for (i = 0; i < num_arrays; i++) { int repack; @@ -4542,7 +4539,6 @@ PHP_FUNCTION(array_multisort) zend_hash_to_packed(hash); } } - HANDLE_UNBLOCK_INTERRUPTIONS(); /* Clean up. */ for (i = 0; i < array_size; i++) { diff --git a/main/main.c b/main/main.c index b0400463f035d..fc183494e2fa6 100644 --- a/main/main.c +++ b/main/main.c @@ -1015,9 +1015,6 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ /* store the error if it has changed */ if (display) { -#ifdef ZEND_SIGNALS - HANDLE_BLOCK_INTERRUPTIONS(); -#endif if (PG(last_error_message)) { free(PG(last_error_message)); PG(last_error_message) = NULL; @@ -1026,9 +1023,6 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ free(PG(last_error_file)); PG(last_error_file) = NULL; } -#ifdef ZEND_SIGNALS - HANDLE_UNBLOCK_INTERRUPTIONS(); -#endif if (!error_filename) { error_filename = "Unknown"; }