Skip to content

Commit

Permalink
Support failed JIT test case: cmp_004.phpt
Browse files Browse the repository at this point in the history
The following opcodes would be generated for $foo:

  0000 #2.CV0($test) [bool] RANGE[0..1] = RECV 1
  0001 #3.CV1($x) [long] RANGE[MIN..MAX] = RECV 2
  0002 JMPZ #2.CV0($test) [bool] RANGE[0..1] BB4
  0003 #4.T2 [bool] ... = IS_SMALLER_OR_EQUAL int(1) #3.CV1($x) ...
  0004 JMP BB5
  ...

The updates in function zend_jit_verify_arg_type() are made to support
RECV opcode.

The updates in function zend_jit_bool_jmpznz() are made to support JMPZ
opcode.

New path is covered in functions zend_jit_cmp() and
zend_jit_cmp_long_long() for IS_SMALLER_OR_EQUAL opcode.
  • Loading branch information
shqking authored and dstogov committed May 18, 2021
1 parent b3519ad commit f8a275d
Showing 1 changed file with 164 additions and 8 deletions.
172 changes: 164 additions & 8 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,28 @@ static void* dasm_labels[zend_lb_MAX];
| brk #0 // TODO
|.endmacro

|.macro LONG_OP_WITH_CONST, long_ins, op1_addr, lval
| brk #0 // TODO
// Define LONG_CMP_WITH_CONST to replace LONG_OP_WITH_CONST in the x86 implementation.
// Note that the 'long_ins' in all use sites of LONG_OP_WITH_CONST are always 'cmp'.
// Note that this macro is different from LONG_CMP.
|.macro LONG_CMP_WITH_CONST, cmp_ins, op1_addr, lval, tmp_reg1, tmp_reg2
|| if (Z_MODE(op1_addr) == IS_MEM_ZVAL) {
| SAFE_MEM_ACC_WITH_UOFFSET ldr, tmp_reg1, Rx(Z_REG(op1_addr)), Z_OFFSET(op1_addr), tmp_reg2
|| if (lval >=0 && lval <= MAX_IMM12) {
| cmp_ins tmp_reg1, #lval
|| } else {
| LOAD_64BIT_VAL tmp_reg2, lval
| cmp_ins tmp_reg1, tmp_reg2
|| }
|| } else if (Z_MODE(op1_addr) == IS_REG) {
|| if (lval >=0 && lval <= MAX_IMM12) {
| cmp_ins Rx(Z_REG(op1_addr)), #lval
|| } else {
| LOAD_64BIT_VAL tmp_reg1, lval
| cmp_ins Rx(Z_REG(op1_addr)), tmp_reg1
|| }
|| } else {
|| ZEND_UNREACHABLE();
|| }
|.endmacro

|.macro GET_ZVAL_LVAL, reg, addr, tmp_reg
Expand Down Expand Up @@ -895,9 +915,11 @@ static void* dasm_labels[zend_lb_MAX];
| IF_NOT_TYPE tmp_reg, val, label
|.endmacro

|.macro CMP_ZVAL_TYPE, addr, val
|.macro CMP_ZVAL_TYPE, addr, val, tmp_reg1, tmp_reg2
|| ZEND_ASSERT(Z_MODE(addr) == IS_MEM_ZVAL);
| cmp byte [Ra(Z_REG(addr))+Z_OFFSET(addr)+offsetof(zval, u1.v.type)], val
|| ZEND_ASSERT(val <= MAX_IMM12);
| SAFE_MEM_ACC_WITH_UOFFSET ldrb, tmp_reg1, Rx(Z_REG(addr)), Z_OFFSET(addr)+offsetof(zval, u1.v.type), tmp_reg2
| cmp tmp_reg1, #val
|.endmacro

|.macro IF_ZVAL_TYPE, addr, val, label, tmp_reg1, tmp_reg2
Expand Down Expand Up @@ -4218,7 +4240,7 @@ static int zend_jit_cmp_long_long(dasm_State **Dst,
}
swap = 1;
} else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_MODE(op2_addr) != IS_CONST_ZVAL) {
| brk #0 // TODO
| LONG_CMP_WITH_CONST cmp, op2_addr, Z_LVAL_P(Z_ZV(op1_addr)), TMP1, TMP2
swap = 1;
} else if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_MODE(op1_addr) != IS_CONST_ZVAL) {
| brk #0 // TODO
Expand Down Expand Up @@ -4311,7 +4333,36 @@ static int zend_jit_cmp_long_long(dasm_State **Dst,
ZEND_UNREACHABLE();
}
} else {
| brk #0 // TODO
switch (opline->opcode) {
case ZEND_IS_EQUAL:
case ZEND_IS_IDENTICAL:
case ZEND_CASE:
case ZEND_CASE_STRICT:
| brk #0 // TODO
break;
case ZEND_IS_NOT_EQUAL:
case ZEND_IS_NOT_IDENTICAL:
| brk #0 // TODO
break;
case ZEND_IS_SMALLER:
if (swap) {
| brk #0 // TODO
} else {
| brk #0 // TODO
}
break;
case ZEND_IS_SMALLER_OR_EQUAL:
if (swap) {
| cset REG0w, ge
} else {
| brk #0 // TODO
}
break;
default:
ZEND_UNREACHABLE();
}
| add REG0w, REG0w, #2
| SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
}

return 1;
Expand Down Expand Up @@ -4608,7 +4659,107 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_
bool set_delayed = 0;
bool jmp_done = 0;

| brk #0 // TODO
if (branch_opcode == ZEND_BOOL) {
set_bool = 1;
} else if (branch_opcode == ZEND_BOOL_NOT) {
set_bool = 1;
set_bool_not = 1;
} else if (branch_opcode == ZEND_JMPZ) {
false_label = target_label;
} else if (branch_opcode == ZEND_JMPNZ) {
true_label = target_label;
} else if (branch_opcode == ZEND_JMPZNZ) {
true_label = target_label2;
false_label = target_label;
} else if (branch_opcode == ZEND_JMPZ_EX) {
set_bool = 1;
false_label = target_label;
} else if (branch_opcode == ZEND_JMPNZ_EX) {
set_bool = 1;
true_label = target_label;
} else {
ZEND_UNREACHABLE();
}

if (Z_MODE(op1_addr) == IS_CONST_ZVAL) {
if (zend_is_true(Z_ZV(op1_addr))) {
/* Always TRUE */
| brk #0 // TODO
} else {
/* Always FALSE */
| brk #0 // TODO
}
return 1;
}

if (op1_info & MAY_BE_REF) {
| brk #0 // TODO
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1x, 0);
}

if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE)) {
if (!(op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY)-MAY_BE_TRUE))) {
/* Always TRUE */
| brk #0 // TODO
} else {
if (!(op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE)))) {
/* Always FALSE */
if (set_bool) {
| brk #0 // TODO
}
} else {
| CMP_ZVAL_TYPE op1_addr, IS_TRUE, TMP1w, TMP2
if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE))) {
| brk #0 // TODO
}
if (!(op1_info & MAY_BE_TRUE)) {
/* It's FALSE */
| brk #0 // TODO
} else {
if (exit_addr) {
| brk #0 // TODO
} else if (true_label != (uint32_t)-1 || false_label != (uint32_t)-1) {
if (set_bool) {
| brk #0 // TODO
} else {
if (true_label != (uint32_t)-1) {
| brk #0 // TODO
} else if (!(op1_info & (MAY_BE_UNDEF|MAY_BE_LONG))) {
| bne =>false_label
jmp_done = 1;
} else {
| brk #0 // TODO
}
}
} else if (set_bool) {
| brk #0 // TODO
}
}
}

/* It's FALSE, but may be UNDEF */
if (op1_info & MAY_BE_UNDEF) {
| brk #0 // TODO
}

if (!jmp_done) {
| brk #0 // TODO
}
}
}

if (op1_info & MAY_BE_LONG) {
| brk #0 // TODO
}

if ((op1_info & MAY_BE_ANY) == MAY_BE_DOUBLE) {
| brk #0 // TODO
} else if (op1_info & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG))) {
| brk #0 // TODO
}

|9:

return 1;
}

Expand Down Expand Up @@ -7023,7 +7174,12 @@ static int zend_jit_verify_arg_type(dasm_State **Dst, const zend_op *opline, zen
|| ZEND_ASSERT(type_code <= MAX_IMM12);
| IF_NOT_ZVAL_TYPE res_addr, type_code, >1, TMP1w, TMP2
} else {
| brk #0 // TODO
| mov REG2w, #1
| SAFE_MEM_ACC_WITH_UOFFSET ldrb, REG1w, Rx(Z_REG(res_addr)), Z_OFFSET(res_addr)+offsetof(zval, u1.v.type), TMP1
| lsl REG2w, REG2w, REG1w
| LOAD_32BIT_VAL TMP1w, type_mask
| tst REG2w, TMP1w
| beq >1
}

|.cold_code
Expand Down

0 comments on commit f8a275d

Please sign in to comment.