summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_execute.h17
-rw-r--r--Zend/zend_vm_def.h32
-rw-r--r--Zend/zend_vm_execute.h32
3 files changed, 61 insertions, 20 deletions
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 5da2e2d9b1..67bac91dd7 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -371,6 +371,23 @@ ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zva
(slot)[1] = (ptr); \
} while (0)
+#define CACHE_SPECIAL (1<<0)
+
+#define IS_SPECIAL_CACHE_VAL(ptr) \
+ (((uintptr_t)(ptr)) & CACHE_SPECIAL)
+
+#define ENCODE_SPECIAL_CACHE_NUM(num) \
+ ((void*)((((uintptr_t)(num)) << 1) | CACHE_SPECIAL))
+
+#define DECODE_SPECIAL_CACHE_NUM(ptr) \
+ (((uintptr_t)(ptr)) >> 1)
+
+#define ENCODE_SPECIAL_CACHE_PTR(ptr) \
+ ((void*)(((uintptr_t)(ptr)) | CACHE_SPECIAL))
+
+#define DECODE_SPECIAL_CACHE_PTR(ptr) \
+ ((void*)(((uintptr_t)(ptr)) & ~CACHE_SPECIAL))
+
#define SKIP_EXT_OPLINE(opline) do { \
while (UNEXPECTED((opline)->opcode >= ZEND_EXT_STMT \
&& (opline)->opcode <= ZEND_TICKS)) { \
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 206452c0a6..72e197e9ed 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5024,8 +5024,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED|CONST_FETCH, CONST, CACHE_SLOT)
USE_OPLINE
zend_constant *c;
- if (EXPECTED(CACHED_PTR(opline->extended_value))) {
- c = CACHED_PTR(opline->extended_value);
+ c = CACHED_PTR(opline->extended_value);
+ if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) {
+ /* pass */
} else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num)) == NULL)) {
SAVE_OPLINE();
@@ -7640,14 +7641,25 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT)
zend_constant *c;
int result;
- if (EXPECTED(CACHED_PTR(opline->extended_value))) {
- result = 1;
- } else if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) {
- result = 0;
- } else {
- CACHE_PTR(opline->extended_value, c);
- result = 1;
- }
+ c = CACHED_PTR(opline->extended_value);
+ do {
+ if (EXPECTED(c != NULL)) {
+ if (!IS_SPECIAL_CACHE_VAL(c)) {
+ result = 1;
+ break;
+ } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
+ result = 0;
+ break;
+ }
+ }
+ if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) {
+ CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
+ result = 0;
+ } else {
+ CACHE_PTR(opline->extended_value, c);
+ result = 1;
+ }
+ } while (0);
ZEND_VM_SMART_BRANCH(result, 0);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
ZEND_VM_NEXT_OPCODE();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 9ddae524c2..b6a6e9753c 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3946,14 +3946,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEN
zend_constant *c;
int result;
- if (EXPECTED(CACHED_PTR(opline->extended_value))) {
- result = 1;
- } else if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) {
- result = 0;
- } else {
- CACHE_PTR(opline->extended_value, c);
- result = 1;
- }
+ c = CACHED_PTR(opline->extended_value);
+ do {
+ if (EXPECTED(c != NULL)) {
+ if (!IS_SPECIAL_CACHE_VAL(c)) {
+ result = 1;
+ break;
+ } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
+ result = 0;
+ break;
+ }
+ }
+ if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) {
+ CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
+ result = 0;
+ } else {
+ CACHE_PTR(opline->extended_value, c);
+ result = 1;
+ }
+ } while (0);
ZEND_VM_SMART_BRANCH(result, 0);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
ZEND_VM_NEXT_OPCODE();
@@ -32040,8 +32051,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
USE_OPLINE
zend_constant *c;
- if (EXPECTED(CACHED_PTR(opline->extended_value))) {
- c = CACHED_PTR(opline->extended_value);
+ c = CACHED_PTR(opline->extended_value);
+ if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) {
+ /* pass */
} else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num)) == NULL)) {
SAVE_OPLINE();