Skip to content

Commit f3e09f0

Browse files
committed
Jit Attribute support
Remove the obsolete doc-comment based JIT trigger. Since function and tracing JITs are recommended for now, the attribute based trigger mode is removed for now. Only @@jit("off") is available to disable the JIT for a function/method.
1 parent 53ef244 commit f3e09f0

File tree

5 files changed

+110
-45
lines changed

5 files changed

+110
-45
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "Zend/zend_exceptions.h"
2424
#include "Zend/zend_constants.h"
2525
#include "Zend/zend_ini.h"
26+
#include "Zend/zend_attributes.h"
2627
#include "zend_smart_str.h"
2728
#include "jit/zend_jit.h"
2829

@@ -3384,28 +3385,29 @@ static int zend_jit_setup_hot_counters(zend_op_array *op_array)
33843385
return SUCCESS;
33853386
}
33863387

3387-
static int zend_needs_manual_jit(const zend_op_array *op_array)
3388+
static int zend_jit_disabled(const zend_op_array *op_array)
33883389
{
3389-
if (op_array->doc_comment) {
3390-
const char *s = ZSTR_VAL(op_array->doc_comment);
3391-
const char *p = strstr(s, "@jit");
3390+
zend_attribute *jit = zend_get_attribute_str(op_array->attributes, "jit", sizeof("jit")-1);
33923391

3393-
if (p) {
3394-
size_t l = ZSTR_LEN(op_array->doc_comment);
3392+
if (jit == NULL || jit->argc == 0) {
3393+
return 0;
3394+
}
33953395

3396-
if ((p == s + 3 || *(p-1) <= ' ') &&
3397-
(p + 6 == s + l || *(p+4) <= ' ')) {
3398-
return 1;
3399-
}
3400-
}
3396+
if (zend_string_equals_literal_ci(Z_STR(jit->args[0].value), "off")) {
3397+
return 1;
34013398
}
3399+
34023400
return 0;
34033401
}
34043402

34053403
#include "jit/zend_jit_trace.c"
34063404

34073405
ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
34083406
{
3407+
if (zend_jit_disabled(op_array)) {
3408+
return SUCCESS;
3409+
}
3410+
34093411
if (dasm_ptr == NULL) {
34103412
return FAILURE;
34113413
}
@@ -3455,12 +3457,6 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
34553457
return zend_jit_setup_hot_trace_counters(op_array);
34563458
} else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
34573459
return zend_real_jit_func(op_array, script, NULL);
3458-
} else if (JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT) {
3459-
if (zend_needs_manual_jit(op_array)) {
3460-
return zend_real_jit_func(op_array, script, NULL);
3461-
} else {
3462-
return SUCCESS;
3463-
}
34643460
} else {
34653461
ZEND_UNREACHABLE();
34663462
}
@@ -3495,21 +3491,19 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
34953491
goto jit_failure;
34963492
}
34973493
}
3498-
} else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD ||
3499-
JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT) {
3494+
} else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
3495+
int do_jit = 1;
35003496

3501-
if (JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT) {
3502-
int do_jit = 0;
3503-
for (i = 0; i < call_graph.op_arrays_count; i++) {
3504-
if (zend_needs_manual_jit(call_graph.op_arrays[i])) {
3505-
do_jit = 1;
3506-
break;
3507-
}
3508-
}
3509-
if (!do_jit) {
3510-
goto jit_failure;
3497+
for (i = 0; i < call_graph.op_arrays_count; i++) {
3498+
if (zend_jit_disabled(call_graph.op_arrays[i])) {
3499+
do_jit = 0;
3500+
break;
35113501
}
35123502
}
3503+
if (!do_jit) {
3504+
goto jit_failure;
3505+
}
3506+
35133507
for (i = 0; i < call_graph.op_arrays_count; i++) {
35143508
info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
35153509
if (info) {
@@ -3531,10 +3525,6 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
35313525
}
35323526

35333527
for (i = 0; i < call_graph.op_arrays_count; i++) {
3534-
if (JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT &&
3535-
!zend_needs_manual_jit(call_graph.op_arrays[i])) {
3536-
continue;
3537-
}
35383528
info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
35393529
if (info) {
35403530
if (zend_jit_op_array_analyze2(call_graph.op_arrays[i], script, &info->ssa, ZCG(accel_directives).optimization_level) != SUCCESS) {
@@ -3546,10 +3536,6 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
35463536

35473537
if (JIT_G(debug) & ZEND_JIT_DEBUG_SSA) {
35483538
for (i = 0; i < call_graph.op_arrays_count; i++) {
3549-
if (JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT &&
3550-
!zend_needs_manual_jit(call_graph.op_arrays[i])) {
3551-
continue;
3552-
}
35533539
info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
35543540
if (info) {
35553541
zend_dump_op_array(call_graph.op_arrays[i], ZEND_DUMP_HIDE_UNREACHABLE|ZEND_DUMP_RC_INFERENCE|ZEND_DUMP_SSA, "JIT", &info->ssa);
@@ -3558,10 +3544,6 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
35583544
}
35593545

35603546
for (i = 0; i < call_graph.op_arrays_count; i++) {
3561-
if (JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT &&
3562-
!zend_needs_manual_jit(call_graph.op_arrays[i])) {
3563-
continue;
3564-
}
35653547
info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
35663548
if (info) {
35673549
if (zend_jit(call_graph.op_arrays[i], &info->ssa, NULL) != SUCCESS) {
@@ -3602,8 +3584,7 @@ ZEND_EXT_API int zend_jit_script(zend_script *script)
36023584
return SUCCESS;
36033585

36043586
jit_failure:
3605-
if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD ||
3606-
JIT_G(trigger) == ZEND_JIT_ON_DOC_COMMENT) {
3587+
if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) {
36073588
for (i = 0; i < call_graph.op_arrays_count; i++) {
36083589
ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
36093590
}
@@ -3716,6 +3697,7 @@ static int zend_jit_parse_config_num(zend_long jit)
37163697

37173698
jit /= 10;
37183699
if (jit % 10 > 5) return FAILURE;
3700+
if (jit % 10 == 4) return FAILURE;
37193701
JIT_G(trigger) = jit % 10;
37203702

37213703
jit /= 10;

ext/opcache/jit/zend_jit.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828

2929
#define ZEND_JIT_ON_SCRIPT_LOAD 0
3030
#define ZEND_JIT_ON_FIRST_EXEC 1
31-
#define ZEND_JIT_ON_PROF_REQUEST 2 /* compile the most frequently caled on first request functions */
31+
#define ZEND_JIT_ON_PROF_REQUEST 2 /* compile the most frequently called on first request functions */
3232
#define ZEND_JIT_ON_HOT_COUNTERS 3 /* compile functions after N calls or loop iterations */
33-
#define ZEND_JIT_ON_DOC_COMMENT 4 /* compile functions with "@jit" tag in doc-comments */
33+
#define ZEND_JIT_ON_ATTRIBUTE 4 /* compile functions with @@Jit attribute, unused at the moment */
3434
#define ZEND_JIT_ON_HOT_TRACE 5 /* trace functions after N calls or loop iterations */
3535

3636
#define ZEND_JIT_REG_ALLOC_LOCAL (1<<0) /* local linear scan register allocation */
@@ -176,4 +176,6 @@ struct _zend_lifetime_interval {
176176
zend_lifetime_interval *list_next;
177177
};
178178

179+
zend_class_entry *zend_ce_opcache_jit_attribute;
180+
179181
#endif /* HAVE_JIT_H */
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
JIT disabled with attributes, assert no jit debug output
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
opcache.jit=1205
9+
opcache.jit_debug=1
10+
opcache.protect_memory=1
11+
--SKIPIF--
12+
<?php require_once('skipif.inc'); ?>
13+
--FILE--
14+
<?php
15+
@@Jit("off")
16+
function foo($a) {
17+
return $a * $a;
18+
}
19+
?>
20+
okey
21+
--EXPECT--
22+
okey
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
JIT trigger with attributes
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
opcache.jit=1205
9+
opcache.jit_debug=1
10+
opcache.protect_memory=1
11+
--SKIPIF--
12+
<?php require_once('skipif.inc'); ?>
13+
--FILE--
14+
<?php
15+
@@Jit("something else")
16+
function foo($a) {
17+
return $a * $a;
18+
}
19+
?>
20+
--EXPECTF--
21+
Fatal error: @@Jit argument $mode only supports the value 'off' %s

ext/opcache/zend_accelerator_module.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "zend_virtual_cwd.h"
3232
#include "ext/standard/info.h"
3333
#include "ext/standard/php_filestat.h"
34+
#include "Zend/zend_attributes.h"
3435
#include "opcache_arginfo.h"
3536

3637
#if HAVE_JIT
@@ -370,12 +371,49 @@ static ZEND_NAMED_FUNCTION(accel_is_readable)
370371
}
371372
}
372373

374+
void zend_jit_validate_opcache_attribute(zend_attribute *jit, uint32_t target, zend_class_entry *scope)
375+
{
376+
if (jit->argc == 0) {
377+
zend_error(E_COMPILE_ERROR, "Too few arguments to attribute @@Jit, %d passed and exactly 1 expected", jit->argc);
378+
}
379+
380+
if (jit->argc > 1) {
381+
zend_error(E_COMPILE_ERROR, "Too many arguments to attribute @@Jit, %d passed and exactly 1 expected", jit->argc);
382+
}
383+
384+
if (jit->argc == 1) {
385+
zend_string *trigger;
386+
387+
if (Z_TYPE(jit->args[0].value) != IS_STRING) {
388+
zend_error(E_COMPILE_ERROR, "@@Jit argument $mode must be a string");
389+
}
390+
391+
trigger = Z_STR(jit->args[0].value);
392+
393+
if (!zend_string_equals_literal_ci(trigger, "off")) {
394+
zend_error(E_COMPILE_ERROR, "@@Jit argument $mode only supports the value 'off'");
395+
}
396+
}
397+
}
398+
373399
static ZEND_MINIT_FUNCTION(zend_accelerator)
374400
{
375401
(void)type; /* keep the compiler happy */
402+
zend_class_entry ce;
403+
zend_internal_attribute *attr;
376404

377405
REGISTER_INI_ENTRIES();
378406

407+
INIT_CLASS_ENTRY(ce, "Jit", NULL);
408+
zend_ce_opcache_jit_attribute = zend_register_internal_class(&ce);
409+
zend_ce_opcache_jit_attribute->ce_flags |= ZEND_ACC_FINAL;
410+
411+
attr = zend_internal_attribute_register(
412+
zend_ce_opcache_jit_attribute,
413+
ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_METHOD
414+
);
415+
attr->validator = zend_jit_validate_opcache_attribute;
416+
379417
return SUCCESS;
380418
}
381419

0 commit comments

Comments
 (0)