diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-11-16 12:05:45 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-11-16 12:05:45 +0300 |
commit | 64dc79f90649f2ca3522ae8d658da4d5707dba29 (patch) | |
tree | ad89529b5fd04af857a9534140035abc460b5044 | |
parent | 7bbed1808613aed5ac30c5c0edc2ce938489a072 (diff) | |
download | php-git-64dc79f90649f2ca3522ae8d658da4d5707dba29.tar.gz |
Trampoline cleanup
-rw-r--r-- | ext/opcache/jit/zend_jit_internal.h | 3 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_trace.c | 16 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_vm_helpers.c | 3 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 4 | ||||
-rw-r--r-- | ext/opcache/tests/jit/trampoline_001.phpt | 34 |
5 files changed, 53 insertions, 7 deletions
diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 22a5aa4100..74b3b8a7e8 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -211,7 +211,8 @@ typedef enum _zend_jit_trace_stop { #define ZEND_JIT_EXIT_FREE_OP1 (1<<5) #define ZEND_JIT_EXIT_FREE_OP2 (1<<6) #define ZEND_JIT_EXIT_PACKED_GUARD (1<<7) -#define ZEND_JIT_EXIT_DYNAMIC_CALL (1<<8) /* exit because of polymorphic INTI_DYNAMIC_CALL call */ +#define ZEND_JIT_EXIT_CLOSURE_CALL (1<<8) /* exit because of polymorphic INIT_DYNAMIC_CALL call */ +#define ZEND_JIT_EXIT_METHOD_CALL (1<<9) /* exit because of polymorphic INIT_METHOD_CALL call */ typedef union _zend_op_trace_info { zend_op dummy; /* the size of this structure must be the same as zend_op */ diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index e15dde5354..31ab4fab06 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -6640,7 +6640,7 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t) if (t->exit_info[i].flags & ZEND_JIT_EXIT_RESTORE_CALL) { fprintf(stderr, "/CALL"); } - if (t->exit_info[i].flags & (ZEND_JIT_EXIT_POLYMORPHISM|ZEND_JIT_EXIT_DYNAMIC_CALL)) { + if (t->exit_info[i].flags & (ZEND_JIT_EXIT_POLYMORPHISM|ZEND_JIT_EXIT_METHOD_CALL|ZEND_JIT_EXIT_CLOSURE_CALL)) { fprintf(stderr, "/POLY"); } if (t->exit_info[i].flags & ZEND_JIT_EXIT_FREE_OP1) { @@ -7043,12 +7043,12 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3 } if (JIT_G(max_polymorphic_calls) > 0) { - if ((zend_jit_traces[parent_num].exit_info[exit_num].flags & ZEND_JIT_EXIT_DYNAMIC_CALL) + if ((zend_jit_traces[parent_num].exit_info[exit_num].flags & (ZEND_JIT_EXIT_METHOD_CALL|ZEND_JIT_EXIT_CLOSURE_CALL)) || ((zend_jit_traces[parent_num].exit_info[exit_num].flags & ZEND_JIT_EXIT_POLYMORPHISM) && EX(call))) { if (zend_jit_traces[parent_num].polymorphism >= JIT_G(max_polymorphic_calls) - 1) { is_megamorphic = zend_jit_traces[parent_num].exit_info[exit_num].flags & - (ZEND_JIT_EXIT_DYNAMIC_CALL | ZEND_JIT_EXIT_POLYMORPHISM); + (ZEND_JIT_EXIT_METHOD_CALL | ZEND_JIT_EXIT_CLOSURE_CALL | ZEND_JIT_EXIT_POLYMORPHISM); } else if (!zend_jit_traces[parent_num].polymorphism) { polymorphism = 1; } else if (exit_num == 0) { @@ -7249,6 +7249,16 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf return 1; } } + if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_METHOD_CALL) { + zend_function *func = (zend_function*)regs->r[0]; + + if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + zend_string_release_ex(func->common.function_name, 0); + zend_free_trampoline(func); + EX(opline) = opline; + return 1; + } + } /* Set VM opline to continue interpretation */ EX(opline) = opline; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 6573200430..6952f7532e 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -928,7 +928,8 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, if (JIT_G(max_polymorphic_calls) == 0 && zend_jit_may_be_polymorphic_call(opline - 1)) { func = NULL; - } else if (is_megamorphic == ZEND_JIT_EXIT_DYNAMIC_CALL + } else if ((is_megamorphic == ZEND_JIT_EXIT_METHOD_CALL + || is_megamorphic == ZEND_JIT_EXIT_CLOSURE_CALL) && trace_buffer[1].opline == opline - 1) { func = NULL; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 7306ee2a3c..42b0e1940c 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -9348,7 +9348,7 @@ static int zend_jit_init_method_call(dasm_State **Dst, int32_t exit_point; const void *exit_addr; - exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_DYNAMIC_CALL); + exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_METHOD_CALL); exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { return 0; @@ -9500,7 +9500,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst, func = (zend_function*)trace->func; opcodes = func->op_array.opcodes; - exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_DYNAMIC_CALL); + exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_CLOSURE_CALL); exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { return 0; diff --git a/ext/opcache/tests/jit/trampoline_001.phpt b/ext/opcache/tests/jit/trampoline_001.phpt new file mode 100644 index 0000000000..21b8b20ee0 --- /dev/null +++ b/ext/opcache/tests/jit/trampoline_001.phpt @@ -0,0 +1,34 @@ +--TEST-- +JIT: trampoline cleanup +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.jit=tracing +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +class A { +} +class B extends A { + function foo() { + echo "B"; + } +} +class C extends A { + function __call($name, $argd) { + echo "C"; + } +} +$b = new B; +$c = new C; +$a = [$b, $b, $b, $c, $c, $c]; +foreach ($a as $x) { + $x->foo(); +} +echo "\n"; +?> +--EXPECT-- +BBBCCC |