Skip to content

Commit 6b59921

Browse files
committed
move literal char handling into scanner
we must be able to know the difference between a one char string and a one char literal string this moves one char string handling to lexer it removes the ability of opcache to cache one char strings marked literal TODO startup literals in scanner at earlier stage TODO known strings?
1 parent 090ed5d commit 6b59921

File tree

8 files changed

+57
-14
lines changed

8 files changed

+57
-14
lines changed

Zend/zend_compile.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,13 @@ static int lookup_cv(zend_string *name) /* {{{ */{
504504
static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
505505
{
506506
ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
507+
508+
if (ZSTR_IS_LITERAL_CHAR(Z_STR_P(zv))) {
509+
Z_TYPE_FLAGS_P(zv) = 0;
510+
511+
return Z_STR_P(zv);
512+
}
513+
507514
Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
508515
if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
509516
Z_TYPE_FLAGS_P(zv) = 0;

Zend/zend_globals.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ struct _zend_php_scanner_globals {
338338
zend_php_scanner_event event, int token, int line,
339339
const char *text, size_t length, void *context);
340340
void *on_event_context;
341+
342+
/* literals */
343+
zend_string chars[256];
344+
zend_string empty;
341345
};
342346

343347
#endif /* ZEND_GLOBALS_H */

Zend/zend_language_scanner.l

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,33 @@ static void yy_scan_buffer(char *str, size_t len)
185185
}
186186
}
187187

188+
static void startup_scanner_literals() {
189+
uint32_t i;
190+
191+
memset(&SCNG(chars), 0, sizeof(SCNG(chars)));
192+
193+
for (i = 0; i < 256; i++) {
194+
zend_string *string = &SCNG(chars)[i];
195+
196+
ZSTR_LEN(string) = 1;
197+
ZSTR_VAL(string)[0] = i;
198+
199+
GC_SET_REFCOUNT(string, 2);
200+
GC_TYPE_INFO(string) =
201+
GC_STRING | IS_STR_LITERAL | (IS_STR_INTERNED|IS_STR_PERMANENT) << GC_FLAGS_SHIFT;
202+
zend_string_hash_func(string);
203+
}
204+
205+
zend_string *empty = &SCNG(empty);
206+
207+
memset(empty, 0, sizeof(zend_string));
208+
209+
GC_SET_REFCOUNT(empty, 2);
210+
GC_TYPE_INFO(empty) =
211+
GC_STRING | IS_STR_LITERAL | (IS_STR_INTERNED|IS_STR_PERMANENT) << GC_FLAGS_SHIFT;
212+
zend_string_hash_func(empty);
213+
}
214+
188215
void startup_scanner(void)
189216
{
190217
CG(parse_error) = 0;
@@ -194,6 +221,8 @@ void startup_scanner(void)
194221
zend_stack_init(&SCNG(nest_location_stack), sizeof(zend_nest_location));
195222
zend_ptr_stack_init(&SCNG(heredoc_label_stack));
196223
SCNG(heredoc_scan_ahead) = 0;
224+
225+
startup_scanner_literals();
197226
}
198227

199228
static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) {
@@ -761,7 +790,7 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename)
761790
}
762791

763792
zend_ast* zend_get_scanned_string_ast(zval *zendlval, uint32_t start_line) {
764-
if (Z_TYPE_P(zendlval) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(zendlval))) {
793+
if (Z_TYPE_P(zendlval) == IS_STRING && Z_STRLEN_P(zendlval) > 1) {
765794
zend_string *string =
766795
Z_STR_P(zendlval);
767796

@@ -904,7 +933,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
904933
ZVAL_STRINGL(zendlval, s, sz); \
905934
efree(s); \
906935
} else if (yyleng == 1) { \
907-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext))); \
936+
ZVAL_INTERNED_STR(zendlval, &SCNG(chars)[(zend_uchar)*(yytext)]); \
908937
} else { \
909938
ZVAL_STRINGL(zendlval, yytext, yyleng); \
910939
}
@@ -922,7 +951,7 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c
922951
if (c == '\n' || c == '\r') {
923952
CG(zend_lineno)++;
924953
}
925-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
954+
ZVAL_INTERNED_STR(zendlval, &SCNG(chars)[c]);
926955
}
927956
goto skip_escape_conversion;
928957
}
@@ -2130,7 +2159,7 @@ string:
21302159

21312160
<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM}|{ONUM} { /* Offset must be treated as a string */
21322161
if (yyleng == 1) {
2133-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext)));
2162+
ZVAL_INTERNED_STR(zendlval, &SCNG(chars)[(zend_uchar)*(yytext)]);
21342163
} else {
21352164
ZVAL_STRINGL(zendlval, yytext, yyleng);
21362165
}
@@ -2285,7 +2314,7 @@ inline_char_handler:
22852314
yyless(readsize);
22862315
}
22872316
} else if (yyleng == 1) {
2288-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*yytext));
2317+
ZVAL_INTERNED_STR(zendlval, &SCNG(chars)[(zend_uchar)*yytext]);
22892318
} else {
22902319
ZVAL_STRINGL(zendlval, yytext, yyleng);
22912320
}
@@ -2466,7 +2495,7 @@ inline_char_handler:
24662495
if (c == '\n' || c == '\r') {
24672496
CG(zend_lineno)++;
24682497
}
2469-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
2498+
ZVAL_INTERNED_STR(zendlval, &SCNG(chars)[c]);
24702499
}
24712500
goto skip_escape_conversion;
24722501
}

Zend/zend_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ static zend_always_inline void zend_string_release_ex(zend_string *s, bool persi
331331
}
332332

333333
#define ZSTR_IS_LITERAL(s) (GC_TYPE_INFO(s) & IS_STR_LITERAL)
334+
#define ZSTR_IS_LITERAL_CHAR(s) (ZSTR_IS_LITERAL(s) && (ZSTR_LEN(s) == 1))
334335

335336
static zend_always_inline zend_string* zend_string_set_literal(zend_string *s) {
336337
if (UNEXPECTED(ZSTR_IS_LITERAL(s))) {

ext/opcache/ZendAccelerator.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,12 +427,12 @@ static void accel_interned_strings_save_state(void)
427427
}
428428

429429
static zend_always_inline zend_string *accel_find_interned_string(zend_string *str)
430-
{
430+
{
431431
zend_ulong h;
432432
uint32_t pos;
433433
zend_string *s;
434434

435-
if (IS_ACCEL_INTERNED(str)) {
435+
if (IS_ACCEL_INTERNED(str) || ZSTR_IS_LITERAL_CHAR(str)) {
436436
/* this is already an interned string */
437437
return str;
438438
}
@@ -471,7 +471,7 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str)
471471
return str;
472472
}
473473

474-
if (IS_ACCEL_INTERNED(str)) {
474+
if (IS_ACCEL_INTERNED(str) || ZSTR_IS_LITERAL_CHAR(str)) {
475475
/* this is already an interned string */
476476
return str;
477477
}
@@ -1368,7 +1368,7 @@ static zend_string* accel_new_interned_key(zend_string *key)
13681368
{
13691369
zend_string *new_key;
13701370

1371-
if (zend_accel_in_shm(key)) {
1371+
if (zend_accel_in_shm(key) || ZSTR_IS_LITERAL_CHAR(key)) {
13721372
return key;
13731373
}
13741374
GC_ADDREF(key);
@@ -2414,7 +2414,7 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
24142414
entry->dependencies = (zend_class_dependency*)ZCG(mem);
24152415
ZEND_HASH_FOREACH_STR_KEY_PTR(dependencies, dep_name, dep_ce) {
24162416
#if ZEND_DEBUG
2417-
ZEND_ASSERT(zend_accel_in_shm(dep_name));
2417+
ZEND_ASSERT(zend_accel_in_shm(dep_name) || ZSTR_IS_LITERAL_CHAR(dep_name));
24182418
#endif
24192419
entry->dependencies[i].name = dep_name;
24202420
entry->dependencies[i].ce = dep_ce;

ext/opcache/zend_file_cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ static int zend_file_cache_flock(int fd, int type)
135135
} while (0)
136136
#define SERIALIZE_STR(ptr) do { \
137137
if (ptr) { \
138-
if (IS_ACCEL_INTERNED(ptr)) { \
138+
if (IS_ACCEL_INTERNED(ptr) || (ZSTR_IS_LITERAL(ptr) && ZSTR_LEN(ptr) == 1)) { \
139139
(ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
140140
} else { \
141141
ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \

ext/opcache/zend_persist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
} \
7070
} while (0)
7171
#define zend_accel_store_interned_string(str) do { \
72-
if (!IS_ACCEL_INTERNED(str)) { \
72+
if (!IS_ACCEL_INTERNED(str) && !ZSTR_IS_LITERAL_CHAR(str)) { \
7373
zend_accel_store_string(str); \
7474
} \
7575
} while (0)

ext/opcache/zend_persist_calc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
# define ADD_STRING(str) ADD_DUP_SIZE((str), _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)))
3434

3535
# define ADD_INTERNED_STRING(str) do { \
36-
if (ZCG(current_persistent_script)->corrupted) { \
36+
if (ZSTR_IS_LITERAL_CHAR(str)) { \
37+
break; \
38+
} else if (ZCG(current_persistent_script)->corrupted) { \
3739
ADD_STRING(str); \
3840
} else if (!IS_ACCEL_INTERNED(str)) { \
3941
zend_string *tmp = accel_new_interned_string(str); \

0 commit comments

Comments
 (0)