Skip to content

Commit 87d7a0b

Browse files
committed
Implement ZEND_JMP_FRAMELESS instruction
1 parent 43eb04c commit 87d7a0b

26 files changed

+906
-594
lines changed

Zend/Optimizer/block_pass.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
10171017
case ZEND_ASSERT_CHECK:
10181018
case ZEND_JMP_NULL:
10191019
case ZEND_BIND_INIT_STATIC_OR_JMP:
1020+
case ZEND_JMP_FRAMELESS:
10201021
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start);
10211022
break;
10221023
case ZEND_CATCH:

Zend/Optimizer/compact_literals.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
770770
break;
771771
case ZEND_DECLARE_ANON_CLASS:
772772
case ZEND_DECLARE_CLASS_DELAYED:
773+
case ZEND_JMP_FRAMELESS:
773774
opline->extended_value = cache_size;
774775
cache_size += sizeof(void *);
775776
break;

Zend/Optimizer/dce.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ static inline bool may_have_side_effects(
146146
case ZEND_ASSERT_CHECK:
147147
case ZEND_JMP_NULL:
148148
case ZEND_BIND_INIT_STATIC_OR_JMP:
149+
case ZEND_JMP_FRAMELESS:
149150
/* For our purposes a jumps and branches are side effects. */
150151
return 1;
151152
case ZEND_BEGIN_SILENCE:

Zend/Optimizer/dfa_pass.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa
653653
case ZEND_ASSERT_CHECK:
654654
case ZEND_JMP_NULL:
655655
case ZEND_BIND_INIT_STATIC_OR_JMP:
656+
case ZEND_JMP_FRAMELESS:
656657
if (ZEND_OP2_JMP_ADDR(opline) == op_array->opcodes + old->start) {
657658
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, op_array->opcodes + dst->start);
658659
}

Zend/Optimizer/pass1.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
355355
case ZEND_JMP_NULL:
356356
case ZEND_VERIFY_NEVER_TYPE:
357357
case ZEND_BIND_INIT_STATIC_OR_JMP:
358+
case ZEND_JMP_FRAMELESS:
358359
collect_constants = 0;
359360
break;
360361
}

Zend/Optimizer/zend_cfg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
370370
case ZEND_ASSERT_CHECK:
371371
case ZEND_JMP_NULL:
372372
case ZEND_BIND_INIT_STATIC_OR_JMP:
373+
case ZEND_JMP_FRAMELESS:
373374
BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
374375
BB_START(i + 1);
375376
break;
@@ -524,6 +525,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
524525
case ZEND_ASSERT_CHECK:
525526
case ZEND_JMP_NULL:
526527
case ZEND_BIND_INIT_STATIC_OR_JMP:
528+
case ZEND_JMP_FRAMELESS:
527529
block->successors_count = 2;
528530
block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes];
529531
block->successors[1] = j + 1;

Zend/Optimizer/zend_inference.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4917,6 +4917,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
49174917
case ZEND_COPY_TMP:
49184918
case ZEND_CASE_STRICT:
49194919
case ZEND_JMP_NULL:
4920+
case ZEND_JMP_FRAMELESS:
49204921
return 0;
49214922
case ZEND_SEND_VAR:
49224923
case ZEND_SEND_VAL:

Zend/Optimizer/zend_optimizer.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z
721721
case ZEND_ASSERT_CHECK:
722722
case ZEND_JMP_NULL:
723723
case ZEND_BIND_INIT_STATIC_OR_JMP:
724+
case ZEND_JMP_FRAMELESS:
724725
ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline));
725726
break;
726727
case ZEND_FE_FETCH_R:
@@ -765,6 +766,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_
765766
case ZEND_ASSERT_CHECK:
766767
case ZEND_JMP_NULL:
767768
case ZEND_BIND_INIT_STATIC_OR_JMP:
769+
case ZEND_JMP_FRAMELESS:
768770
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]);
769771
break;
770772
case ZEND_CATCH:
@@ -1160,6 +1162,7 @@ static void zend_redo_pass_two(zend_op_array *op_array)
11601162
case ZEND_ASSERT_CHECK:
11611163
case ZEND_JMP_NULL:
11621164
case ZEND_BIND_INIT_STATIC_OR_JMP:
1165+
case ZEND_JMP_FRAMELESS:
11631166
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
11641167
break;
11651168
case ZEND_CATCH:
@@ -1281,6 +1284,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
12811284
case ZEND_ASSERT_CHECK:
12821285
case ZEND_JMP_NULL:
12831286
case ZEND_BIND_INIT_STATIC_OR_JMP:
1287+
case ZEND_JMP_FRAMELESS:
12841288
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes];
12851289
break;
12861290
case ZEND_CATCH:

Zend/tests/frameless_jmp_001.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Frameless jmp
3+
--FILE--
4+
<?php
5+
namespace Foo;
6+
function test($needle, $haystack) {
7+
return in_array($needle, $haystack, true);
8+
}
9+
var_dump(test('foo', ['foo', 'bar']));
10+
?>
11+
--EXPECT--
12+
bool(true)

Zend/tests/frameless_jmp_002.phpt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Frameless jmp
3+
--FILE--
4+
<?php
5+
namespace Foo;
6+
var_dump(class_exists('\foo'));
7+
?>
8+
--EXPECT--
9+
bool(false)

Zend/tests/frameless_jmp_003.phpt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Frameless jmp
3+
--FILE--
4+
<?php
5+
namespace Foo;
6+
preg_replace('/foo/', '', '');
7+
?>
8+
--EXPECT--

Zend/tests/frameless_jmp_004.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Frameless jmp
3+
--FILE--
4+
<?php
5+
namespace Foo;
6+
function declare_local_class_exists() {
7+
function class_exists() {
8+
var_dump(__FUNCTION__);
9+
return true;
10+
}
11+
}
12+
var_dump(CLASS_EXISTS('Foo'));
13+
declare_local_class_exists();
14+
var_dump(CLASS_EXISTS('Foo'));
15+
?>
16+
--EXPECT--
17+
bool(false)
18+
string(16) "Foo\class_exists"
19+
bool(true)

Zend/tests/frameless_jmp_005.phpt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Frameless jmp
3+
--FILE--
4+
<?php
5+
namespace Foo;
6+
var_dump(preg_replace("/foo/", '', '', 1));
7+
?>
8+
--EXPECT--
9+
string(0) ""

Zend/zend.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,13 @@ void zend_shutdown(void) /* {{{ */
11311131
/* Child classes may reuse structures from parent classes, so destroy in reverse order. */
11321132
zend_hash_graceful_reverse_destroy(GLOBAL_CLASS_TABLE);
11331133

1134+
zend_flf_capacity = 0;
1135+
zend_flf_count = 0;
1136+
free(zend_flf_functions);
1137+
free(zend_flf_handlers);
1138+
zend_flf_functions = NULL;
1139+
zend_flf_handlers = NULL;
1140+
11341141
zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
11351142
free(GLOBAL_AUTO_GLOBALS_TABLE);
11361143

0 commit comments

Comments
 (0)