Skip to content

Commit 25f4510

Browse files
authored
Merge JMP_FRAMELESS cache slots in Optimizer/compact_literals (#18093)
This avoids repeated lookups in the function table for the same function name. Although this optimization is observable, i.e. defining a function via an include in between 2 JMP_FRAMELESS for the same function, this cannot be relied on already as far as I know if the optimizer runs.
1 parent d7e2f28 commit 25f4510

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

Zend/Optimizer/compact_literals.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
165165
HashTable hash;
166166
zend_string *key = NULL;
167167
void *checkpoint = zend_arena_checkpoint(ctx->arena);
168-
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
168+
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot, *jmp_slot;
169169

170170
if (op_array->last_literal) {
171171
info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
@@ -175,6 +175,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
175175
end = opline + op_array->last;
176176
while (opline < end) {
177177
switch (opline->opcode) {
178+
case ZEND_JMP_FRAMELESS:
179+
LITERAL_INFO(opline->op1.constant, 1);
180+
break;
178181
case ZEND_INIT_FCALL_BY_NAME:
179182
LITERAL_INFO(opline->op2.constant, 2);
180183
break;
@@ -480,13 +483,14 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
480483
zend_hash_clean(&hash);
481484
op_array->last_literal = j;
482485

483-
const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
484-
memset(const_slot, -1, j * 6 * sizeof(int));
486+
const_slot = zend_arena_alloc(&ctx->arena, j * 7 * sizeof(int));
487+
memset(const_slot, -1, j * 7 * sizeof(int));
485488
class_slot = const_slot + j;
486489
func_slot = class_slot + j;
487490
bind_var_slot = func_slot + j;
488491
property_slot = bind_var_slot + j;
489492
method_slot = property_slot + j;
493+
jmp_slot = method_slot + j;
490494

491495
/* Update opcodes to use new literals table */
492496
cache_size = zend_op_array_extension_handles * sizeof(void*);
@@ -773,10 +777,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
773777
break;
774778
case ZEND_DECLARE_ANON_CLASS:
775779
case ZEND_DECLARE_CLASS_DELAYED:
776-
case ZEND_JMP_FRAMELESS:
777780
opline->extended_value = cache_size;
778781
cache_size += sizeof(void *);
779782
break;
783+
case ZEND_JMP_FRAMELESS:
784+
// op1 func
785+
if (jmp_slot[opline->op1.constant] >= 0) {
786+
opline->extended_value = jmp_slot[opline->op1.constant];
787+
} else {
788+
opline->extended_value = cache_size;
789+
cache_size += sizeof(void *);
790+
jmp_slot[opline->op1.constant] = opline->extended_value;
791+
}
792+
break;
780793
case ZEND_SEND_VAL:
781794
case ZEND_SEND_VAL_EX:
782795
case ZEND_SEND_VAR:

0 commit comments

Comments
 (0)