]> granicus.if.org Git - php/commitdiff
Speed up ZEND_SWITCH_STRING/ZEND_SWITCH_LONG for wrong type
authorTyson Andre <tysonandre775@hotmail.com>
Sun, 19 Apr 2020 15:53:36 +0000 (11:53 -0400)
committerTyson Andre <tysonandre775@hotmail.com>
Sun, 19 Apr 2020 21:31:18 +0000 (17:31 -0400)
This has the minor benefit of avoiding loading the address of the
jump table when the expression for the switch isn't a string/long.
gcc doesn't seem to optimize that.

The previous function body is the original implementation: ad8652818a5

```
// Before: 0.267s, after: 0.265s
function test_switch($x) {
    for ($i = 0; $i < 10000000; $i++) {
        switch ($x) {
        case 'a':
        case 'b':
            echo "i=$i\n";
        }
    }
}
test_switch(null);
```

Closes GH-5419

Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 0797322a86d384fe9a83a14033657e1124f55ca7..6a4719b3dd28f06d744d5cc328b25925730b2fea 100644 (file)
@@ -8348,7 +8348,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JM
        HashTable *jumptable;
 
        op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
-       jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
 
        if (Z_TYPE_P(op) != IS_LONG) {
                ZVAL_DEREF(op);
@@ -8358,6 +8357,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JM
                }
        }
 
+       jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
        jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
@@ -8376,7 +8376,6 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST,
        HashTable *jumptable;
 
        op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
-       jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
 
        if (Z_TYPE_P(op) != IS_STRING) {
                if (OP1_TYPE == IS_CONST) {
@@ -8391,6 +8390,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST,
                }
        }
 
+       jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
        jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
index 33e97f2b0489fcc057236de58bcb963e5e102f73..346dbec656f9a6157d0a1200a6570cd556be85bc 100644 (file)
@@ -6454,7 +6454,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_
        HashTable *jumptable;
 
        op = RT_CONSTANT(opline, opline->op1);
-       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
 
        if (Z_TYPE_P(op) != IS_LONG) {
                ZVAL_DEREF(op);
@@ -6464,6 +6463,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_
                }
        }
 
+       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
        jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
@@ -6482,7 +6482,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE
        HashTable *jumptable;
 
        op = RT_CONSTANT(opline, opline->op1);
-       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
 
        if (Z_TYPE_P(op) != IS_STRING) {
                if (IS_CONST == IS_CONST) {
@@ -6497,6 +6496,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE
                }
        }
 
+       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
        jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST);
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
@@ -11316,7 +11316,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS
        HashTable *jumptable;
 
        op = EX_VAR(opline->op1.var);
-       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
 
        if (Z_TYPE_P(op) != IS_LONG) {
                ZVAL_DEREF(op);
@@ -11326,6 +11325,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS
                }
        }
 
+       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
        jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
@@ -11344,7 +11344,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO
        HashTable *jumptable;
 
        op = EX_VAR(opline->op1.var);
-       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
 
        if (Z_TYPE_P(op) != IS_STRING) {
                if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) {
@@ -11359,6 +11358,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO
                }
        }
 
+       jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
        jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST);
        if (jump_zv != NULL) {
                ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));