Skip to content

Commit 4033c11

Browse files
committed
Revisit 32-bit logical operations with constants
Add macro "BW_OP_32_WITH_CONST" for safe 32-bit logical operations with constants. Add macro "GET_LOW_8BITS" for 'and' operation with "0xff". Change-Id: I57968069b43ac4c02d876e9290433a74b9d87742
1 parent f37b9ac commit 4033c11

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,23 @@ static int logical_immediate_p (uint64_t value, uint32_t reg_size)
227227
|| }
228228
|.endmacro
229229

230+
// Extract the low 8 bits from 'src_reg' into 'dst_reg'. 0xff can be encoded as imm for 'and' instruction.
231+
|.macro GET_LOW_8BITS, dst_reg, src_reg
232+
| and dst_reg, src_reg, #0xff
233+
|.endmacro
234+
235+
// Bitwise operation with constants. 'ins' can be and/orr/eor/ands. Operands are 32-bit.
236+
|.macro BW_OP_32_WITH_CONST, ins, reg, op, val, tmp_reg
237+
|| if (val == 0) {
238+
| ins reg, op, wzr
239+
|| } else if (logical_immediate_p((uint32_t)val, 32)) {
240+
| ins reg, op, #val
241+
|| } else {
242+
| LOAD_32BIT_VAL tmp_reg, val
243+
| ins reg, op, tmp_reg
244+
|| }
245+
|.endmacro
246+
230247
// Bitwise operation with constants. 'ins' can be and/orr/eor/ands. Operands are 64-bit.
231248
|.macro BW_OP_64_WITH_CONST, ins, reg, op, val, tmp_reg
232249
|| if (val == 0) {
@@ -8375,8 +8392,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
83758392
| str TMP1w, EX:RX->This.u1.type_info
83768393
} else {
83778394
| ldr TMP1w, EX:RX->This.u1.type_info
8378-
| LOAD_32BIT_VAL TMP2w, (ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS)
8379-
| orr TMP1w, TMP1w, TMP2w
8395+
| BW_OP_32_WITH_CONST orr, TMP1w, TMP1w, (ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS), TMP2w
83808396
| str TMP1w, EX:RX->This.u1.type_info
83818397
}
83828398
}
@@ -8396,16 +8412,14 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
83968412
| // call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_CLOSURE |
83978413
| // (closure->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE);
83988414
| ldr REG2w, [REG0, #offsetof(zend_closure, func.common.fn_flags)]
8399-
| and REG2w, REG2w, #ZEND_ACC_FAKE_CLOSURE
8400-
| LOAD_32BIT_VAL TMP1w, (ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_CLOSURE)
8401-
| orr REG2w, REG2w, TMP1w
8415+
| BW_OP_32_WITH_CONST and, REG2w, REG2w, ZEND_ACC_FAKE_CLOSURE, TMP1w
8416+
| BW_OP_32_WITH_CONST orr, REG2w, REG2w, (ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_CLOSURE), TMP1w
84028417
| // if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {
84038418
| ldrb TMP1w, [REG0, #offsetof(zend_closure, this_ptr.u1.v.type)]
84048419
| cmp TMP1w, #IS_UNDEF
84058420
| beq >1
84068421
| // call_info |= ZEND_CALL_HAS_THIS;
8407-
| LOAD_32BIT_VAL TMP1w, ZEND_CALL_HAS_THIS
8408-
| orr REG2w, REG2w, TMP1w
8422+
| BW_OP_32_WITH_CONST orr, REG2w, REG2w, ZEND_CALL_HAS_THIS, TMP1w
84098423
| // object_or_called_scope = Z_OBJ(closure->this_ptr);
84108424
| ldr REG1, [REG0, #offsetof(zend_closure, this_ptr.value.ptr)]
84118425
|1:
@@ -9267,7 +9281,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
92679281
| mov FCARG1x, RX
92689282
}
92699283
| EXT_CALL zend_jit_deprecated_helper, REG0
9270-
| and RETVALw, RETVALw, #0xff
9284+
| GET_LOW_8BITS RETVALw, RETVALw
92719285
| cmp RETVALw, #0 // Result is 0 on exception
92729286
| ldr REG0, EX:RX->func // reload
92739287
| bne >1
@@ -9561,7 +9575,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
95619575
| mov FCARG1x, RX
95629576
}
95639577
| EXT_CALL zend_jit_deprecated_helper, REG0
9564-
| and RETVALw, RETVALw, #0xff
9578+
| GET_LOW_8BITS RETVALw, RETVALw
95659579
| cmp RETVALw, #0 // Result is 0 on exception
95669580
| ldr REG0, EX:RX->func // reload
95679581
| bne >1
@@ -9940,7 +9954,7 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend
99409954
if (!exit_addr) {
99419955
return 0;
99429956
}
9943-
| and TMP1w, REG1w, #0xff
9957+
| GET_LOW_8BITS TMP1w, REG1w
99449958
| cmp TMP1w, #IS_REFERENCE
99459959
| bne &exit_addr
99469960
}
@@ -9961,7 +9975,7 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend
99619975

99629976
| ZVAL_COPY_VALUE arg_addr, MAY_BE_ANY, op1_addr, op1_info, ZREG_REG1, ZREG_REG2, ZREG_TMP1, ZREG_TMP2, ZREG_FPR0
99639977
if (op1_info & MAY_BE_REF) {
9964-
| and TMP1w, REG1w, #0xff
9978+
| GET_LOW_8BITS TMP1w, REG1w
99659979
| cmp TMP1w, #IS_REFERENCE
99669980
| beq >7
99679981
}
@@ -10037,7 +10051,7 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend
1003710051
if (opline->opcode == ZEND_SEND_VAR_NO_REF) {
1003810052
| ZVAL_COPY_VALUE arg_addr, MAY_BE_ANY, op1_addr, op1_info, ZREG_REG1, ZREG_REG2, ZREG_TMP1, ZREG_TMP2, ZREG_FPR0
1003910053
if (op1_info & MAY_BE_REF) {
10040-
| and TMP1w, REG1w, #0xff
10054+
| GET_LOW_8BITS TMP1w, REG1w
1004110055
| cmp TMP1w, #IS_REFERENCE
1004210056
| beq >7
1004310057
}
@@ -10121,12 +10135,12 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline)
1012110135
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
1012210136
|| if (reuse_ip) {
1012310137
| ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
10124-
| orr TMP1w, TMP1w, #ZEND_CALL_SEND_ARG_BY_REF
10138+
| BW_OP_32_WITH_CONST orr, TMP1w, TMP1w, ZEND_CALL_SEND_ARG_BY_REF, TMP2w
1012510139
| str TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
1012610140
|| } else {
1012710141
| ldr REG0, EX->call
1012810142
| ldr TMP1w, [REG0, #offsetof(zend_execute_data, This.u1.type_info)]
10129-
| orr TMP1w, TMP1w, #ZEND_CALL_SEND_ARG_BY_REF
10143+
| BW_OP_32_WITH_CONST orr, TMP1w, TMP1w, ZEND_CALL_SEND_ARG_BY_REF, TMP2w
1013010144
| str TMP1w, [REG0, #offsetof(zend_execute_data, This.u1.type_info)]
1013110145
|| }
1013210146
}
@@ -10136,12 +10150,12 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline)
1013610150
| // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
1013710151
|| if (reuse_ip) {
1013810152
| ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
10139-
| and TMP1w, TMP1w, #(~ZEND_CALL_SEND_ARG_BY_REF)
10153+
| BW_OP_32_WITH_CONST and, TMP1w, TMP1w, (~ZEND_CALL_SEND_ARG_BY_REF), TMP2w
1014010154
| str TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
1014110155
|| } else {
1014210156
| ldr REG0, EX->call
1014310157
| ldr TMP1w, [REG0, #offsetof(zend_execute_data, This.u1.type_info)]
10144-
| and TMP1w, TMP1w, #(~ZEND_CALL_SEND_ARG_BY_REF)
10158+
| BW_OP_32_WITH_CONST and, TMP1w, TMP1w, (~ZEND_CALL_SEND_ARG_BY_REF), TMP2w
1014510159
| str TMP1w, [REG0, #offsetof(zend_execute_data, This.u1.type_info)]
1014610160
|| }
1014710161
}
@@ -10162,8 +10176,7 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline)
1016210176
|1:
1016310177
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
1016410178
| ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
10165-
| LOAD_32BIT_VAL TMP2w, ZEND_CALL_SEND_ARG_BY_REF
10166-
| orr TMP1w, TMP1w, TMP2w
10179+
| BW_OP_32_WITH_CONST orr, TMP1w, TMP1w, ZEND_CALL_SEND_ARG_BY_REF, TMP2w
1016710180
| str TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
1016810181
| b >1
1016910182
|.code
@@ -11078,7 +11091,7 @@ static int zend_jit_zval_copy_deref(dasm_State **Dst, zend_jit_addr res_addr, ze
1107811091

1107911092
| GET_ZVAL_PTR REG1, val_addr, TMP1
1108011093
| IF_NOT_REFCOUNTED REG2w, >2, TMP1w
11081-
| and TMP2w, REG2w, #0xff // TMP2w -> low 8 bits of REG2w
11094+
| GET_LOW_8BITS TMP2w, REG2w
1108211095
| IF_NOT_TYPE TMP2w, IS_REFERENCE, >1
1108311096
| add REG1, REG1, #offsetof(zend_reference, val)
1108411097
| GET_Z_TYPE_INFO REG2w, REG1
@@ -11372,7 +11385,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
1137211385
| IF_NOT_ZVAL_TYPE val_addr, type, &res_exit_addr, TMP1w, TMP2
1137311386
} else {
1137411387
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
11375-
| and TMP1w, REG2w, #0xff
11388+
| GET_LOW_8BITS TMP1w, REG2w
1137611389
| IF_NOT_TYPE TMP1w, type, &res_exit_addr
1137711390
}
1137811391
| // ZVAL_COPY
@@ -11929,7 +11942,7 @@ static int zend_jit_verify_arg_type(dasm_State **Dst, const zend_op *opline, zen
1192911942
| mov REG0w, RETVALw
1193011943

1193111944
if (check_exception) {
11932-
| and REG0w, REG0w, #0xff
11945+
| GET_LOW_8BITS REG0w, REG0w
1193311946
| tst REG0w, REG0w
1193411947
if (in_cold) {
1193511948
| bne >1
@@ -12346,7 +12359,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1234612359
|.code
1234712360
}
1234812361
} else if (flags == ZEND_FETCH_REF) {
12349-
| and TMP1w, REG2w, #0xff
12362+
| GET_LOW_8BITS TMP1w, REG2w
1235012363
| IF_TYPE TMP1w, IS_REFERENCE, >1
1235112364
if (ce && ce->ce_flags & ZEND_ACC_IMMUTABLE) {
1235212365
| LOAD_ADDR FCARG2x, prop_info
@@ -12428,7 +12441,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1242812441
type = concrete_type(res_info);
1242912442

1243012443
| // ZVAL_DEREF()
12431-
| and TMP1w, REG2w, #0xff
12444+
| GET_LOW_8BITS TMP1w, REG2w
1243212445
| IF_NOT_TYPE TMP1w, IS_REFERENCE, >1
1243312446
| GET_Z_PTR REG0, REG0
1243412447
| add REG0, REG0, #offsetof(zend_reference, val)
@@ -12438,7 +12451,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
1243812451
} else {
1243912452
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
1244012453
|1:
12441-
| and TMP1w, REG2w, #0xff
12454+
| GET_LOW_8BITS TMP1w, REG2w
1244212455
| IF_NOT_TYPE TMP1w, type, &exit_addr
1244312456
}
1244412457
| // ZVAL_COPY

0 commit comments

Comments
 (0)