Skip to content

Commit 0381c1b

Browse files
committed
Fixed bug #69388
Renamed compiler_context to oparray_context. Introduced per-file file_context. Moved import tables into the file_context. context_stack no longer exists, instead keeping backups of contexts on C stack. Same for file contexts. TODO: Move more things out of CG into file_context. There should be a number of other things that we should not try to reuse in nested compilations.
1 parent b991741 commit 0381c1b

File tree

6 files changed

+477
-445
lines changed

6 files changed

+477
-445
lines changed

Zend/zend.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
10471047
zend_class_entry *saved_class_entry;
10481048
zend_stack loop_var_stack;
10491049
zend_stack delayed_oplines_stack;
1050-
zend_stack context_stack;
10511050
zend_array *symbol_table;
10521051

10531052
if (type & E_EXCEPTION) {
@@ -1234,7 +1233,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
12341233
CG(active_class_entry) = NULL;
12351234
SAVE_STACK(loop_var_stack);
12361235
SAVE_STACK(delayed_oplines_stack);
1237-
SAVE_STACK(context_stack);
12381236
CG(in_compilation) = 0;
12391237
}
12401238

@@ -1254,7 +1252,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
12541252
CG(active_class_entry) = saved_class_entry;
12551253
RESTORE_STACK(loop_var_stack);
12561254
RESTORE_STACK(delayed_oplines_stack);
1257-
RESTORE_STACK(context_stack);
12581255
CG(in_compilation) = 1;
12591256
}
12601257

Zend/zend_compile.c

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ static void init_compiler_declarables(void) /* {{{ */
225225
}
226226
/* }}} */
227227

228-
void zend_init_compiler_context(void) /* {{{ */
228+
void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
229229
{
230+
*prev_context = CG(context);
230231
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
231232
CG(context).vars_size = 0;
232233
CG(context).literals_size = 0;
@@ -238,6 +239,56 @@ void zend_init_compiler_context(void) /* {{{ */
238239
}
239240
/* }}} */
240241

242+
void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
243+
{
244+
if (CG(context).labels) {
245+
zend_hash_destroy(CG(context).labels);
246+
FREE_HASHTABLE(CG(context).labels);
247+
CG(context).labels = NULL;
248+
}
249+
CG(context) = *prev_context;
250+
}
251+
/* }}} */
252+
253+
static void zend_reset_import_tables(void) /* {{{ */
254+
{
255+
zend_file_context *ctx = &CG(file_context);
256+
if (ctx->imports) {
257+
zend_hash_destroy(ctx->imports);
258+
efree(ctx->imports);
259+
ctx->imports = NULL;
260+
}
261+
262+
if (ctx->imports_function) {
263+
zend_hash_destroy(ctx->imports_function);
264+
efree(ctx->imports_function);
265+
ctx->imports_function = NULL;
266+
}
267+
268+
if (ctx->imports_const) {
269+
zend_hash_destroy(ctx->imports_const);
270+
efree(ctx->imports_const);
271+
ctx->imports_const = NULL;
272+
}
273+
}
274+
/* }}} */
275+
276+
void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
277+
{
278+
*prev_context = CG(file_context);
279+
CG(file_context).imports = NULL;
280+
CG(file_context).imports_function = NULL;
281+
CG(file_context).imports_const = NULL;
282+
}
283+
/* }}} */
284+
285+
void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
286+
{
287+
zend_reset_import_tables();
288+
CG(file_context) = *prev_context;
289+
}
290+
/* }}} */
291+
241292
void zend_init_compiler_data_structures(void) /* {{{ */
242293
{
243294
zend_stack_init(&CG(loop_var_stack), sizeof(znode));
@@ -248,12 +299,8 @@ void zend_init_compiler_data_structures(void) /* {{{ */
248299
CG(current_namespace) = NULL;
249300
CG(in_namespace) = 0;
250301
CG(has_bracketed_namespaces) = 0;
251-
CG(current_import) = NULL;
252-
CG(current_import_function) = NULL;
253-
CG(current_import_const) = NULL;
254302
zend_hash_init(&CG(const_filenames), 8, NULL, NULL, 0);
255303
init_compiler_declarables();
256-
zend_stack_init(&CG(context_stack), sizeof(CG(context)));
257304

258305
CG(encoding_declared) = 0;
259306
}
@@ -285,7 +332,6 @@ void shutdown_compiler(void) /* {{{ */
285332
zend_stack_destroy(&CG(delayed_oplines_stack));
286333
zend_hash_destroy(&CG(filenames_table));
287334
zend_hash_destroy(&CG(const_filenames));
288-
zend_stack_destroy(&CG(context_stack));
289335
zend_arena_destroy(CG(arena));
290336
}
291337
/* }}} */
@@ -731,10 +777,10 @@ zend_string *zend_resolve_non_class_name(
731777
*is_fully_qualified = 1;
732778
}
733779

734-
if (compound && CG(current_import)) {
780+
if (compound && CG(file_context).imports) {
735781
/* If the first part of a qualified name is an alias, substitute it. */
736782
size_t len = compound - name->val;
737-
zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
783+
zend_string *import_name = zend_hash_find_ptr_lc(CG(file_context).imports, name->val, len);
738784

739785
if (import_name) {
740786
return zend_concat_names(
@@ -749,13 +795,13 @@ zend_string *zend_resolve_non_class_name(
749795
zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
750796
{
751797
return zend_resolve_non_class_name(
752-
name, type, is_fully_qualified, 0, CG(current_import_function));
798+
name, type, is_fully_qualified, 0, CG(file_context).imports_function);
753799
}
754800
/* }}} */
755801

756802
zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
757803
return zend_resolve_non_class_name(
758-
name, type, is_fully_qualified, 1, CG(current_import_const));
804+
name, type, is_fully_qualified, 1, CG(file_context).imports_const);
759805
}
760806
/* }}} */
761807

@@ -781,12 +827,13 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
781827
return name;
782828
}
783829

784-
if (CG(current_import)) {
830+
if (CG(file_context).imports) {
785831
compound = memchr(name->val, '\\', name->len);
786832
if (compound) {
787833
/* If the first part of a qualified name is an alias, substitute it. */
788834
size_t len = compound - name->val;
789-
zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
835+
zend_string *import_name =
836+
zend_hash_find_ptr_lc(CG(file_context).imports, name->val, len);
790837

791838
if (import_name) {
792839
return zend_concat_names(
@@ -795,7 +842,7 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
795842
} else {
796843
/* If an unqualified name is an alias, replace it. */
797844
zend_string *import_name
798-
= zend_hash_find_ptr_lc(CG(current_import), name->val, name->len);
845+
= zend_hash_find_ptr_lc(CG(file_context).imports, name->val, name->len);
799846

800847
if (import_name) {
801848
return zend_string_copy(import_name);
@@ -881,21 +928,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
881928
}
882929
/* }}} */
883930

884-
void zend_release_labels(int temporary) /* {{{ */
885-
{
886-
if (CG(context).labels) {
887-
zend_hash_destroy(CG(context).labels);
888-
FREE_HASHTABLE(CG(context).labels);
889-
CG(context).labels = NULL;
890-
}
891-
if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
892-
zend_compiler_context *ctx = zend_stack_top(&CG(context_stack));
893-
CG(context) = *ctx;
894-
zend_stack_del_top(&CG(context_stack));
895-
}
896-
}
897-
/* }}} */
898-
899931
static zend_bool zend_is_call(zend_ast *ast);
900932

901933
static int generate_free_loop_var(znode *var) /* {{{ */
@@ -1621,28 +1653,6 @@ void zend_verify_namespace(void) /* {{{ */
16211653
}
16221654
/* }}} */
16231655

1624-
static void zend_reset_import_tables(void) /* {{{ */
1625-
{
1626-
if (CG(current_import)) {
1627-
zend_hash_destroy(CG(current_import));
1628-
efree(CG(current_import));
1629-
CG(current_import) = NULL;
1630-
}
1631-
1632-
if (CG(current_import_function)) {
1633-
zend_hash_destroy(CG(current_import_function));
1634-
efree(CG(current_import_function));
1635-
CG(current_import_function) = NULL;
1636-
}
1637-
1638-
if (CG(current_import_const)) {
1639-
zend_hash_destroy(CG(current_import_const));
1640-
efree(CG(current_import_const));
1641-
CG(current_import_const) = NULL;
1642-
}
1643-
}
1644-
/* }}} */
1645-
16461656
static void zend_end_namespace(void) /* {{{ */ {
16471657
CG(in_namespace) = 0;
16481658
zend_reset_import_tables();
@@ -4503,8 +4513,8 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as
45034513

45044514
lcname = zend_string_tolower(name);
45054515

4506-
if (CG(current_import_function)) {
4507-
zend_string *import_name = zend_hash_find_ptr(CG(current_import_function), lcname);
4516+
if (CG(file_context).imports_function) {
4517+
zend_string *import_name = zend_hash_find_ptr(CG(file_context).imports_function, lcname);
45084518
if (import_name && !zend_string_equals_ci(lcname, import_name)) {
45094519
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s "
45104520
"because the name is already in use", name->val);
@@ -4551,6 +4561,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
45514561

45524562
zend_op_array *orig_op_array = CG(active_op_array);
45534563
zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
4564+
zend_oparray_context orig_oparray_context;
45544565

45554566
// TODO.AST interactive (not just here - also bpc etc!)
45564567

@@ -4575,8 +4586,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
45754586
}
45764587

45774588
CG(active_op_array) = op_array;
4578-
zend_stack_push(&CG(context_stack), (void *) &CG(context));
4579-
zend_init_compiler_context();
4589+
zend_oparray_context_begin(&orig_oparray_context);
45804590

45814591
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
45824592
zend_op *opline_ext = zend_emit_op(NULL, ZEND_EXT_NOP, NULL, NULL);
@@ -4606,7 +4616,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
46064616
zend_emit_final_return(NULL);
46074617

46084618
pass_two(CG(active_op_array));
4609-
zend_release_labels(0);
4619+
zend_oparray_context_end(&orig_oparray_context);
46104620

46114621
/* Pop the loop variable stack separator */
46124622
zend_stack_del_top(&CG(loop_var_stack));
@@ -4884,8 +4894,8 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
48844894

48854895
lcname = zend_string_tolower(name);
48864896

4887-
if (CG(current_import)) {
4888-
import_name = zend_hash_find_ptr(CG(current_import), lcname);
4897+
if (CG(file_context).imports) {
4898+
import_name = zend_hash_find_ptr(CG(file_context).imports, lcname);
48894899
}
48904900

48914901
if (CG(current_namespace)) {
@@ -5036,25 +5046,26 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
50365046

50375047
static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
50385048
{
5049+
zend_file_context *ctx = &CG(file_context);
50395050
switch (type) {
50405051
case T_CLASS:
5041-
if (!CG(current_import)) {
5042-
CG(current_import) = emalloc(sizeof(HashTable));
5043-
zend_hash_init(CG(current_import), 8, NULL, str_dtor, 0);
5052+
if (!ctx->imports) {
5053+
ctx->imports = emalloc(sizeof(HashTable));
5054+
zend_hash_init(ctx->imports, 8, NULL, str_dtor, 0);
50445055
}
5045-
return CG(current_import);
5056+
return ctx->imports;
50465057
case T_FUNCTION:
5047-
if (!CG(current_import_function)) {
5048-
CG(current_import_function) = emalloc(sizeof(HashTable));
5049-
zend_hash_init(CG(current_import_function), 8, NULL, str_dtor, 0);
5058+
if (!ctx->imports_function) {
5059+
ctx->imports_function = emalloc(sizeof(HashTable));
5060+
zend_hash_init(ctx->imports_function, 8, NULL, str_dtor, 0);
50505061
}
5051-
return CG(current_import_function);
5062+
return ctx->imports_function;
50525063
case T_CONST:
5053-
if (!CG(current_import_const)) {
5054-
CG(current_import_const) = emalloc(sizeof(HashTable));
5055-
zend_hash_init(CG(current_import_const), 8, NULL, str_dtor, 0);
5064+
if (!ctx->imports_const) {
5065+
ctx->imports_const = emalloc(sizeof(HashTable));
5066+
zend_hash_init(ctx->imports_const, 8, NULL, str_dtor, 0);
50565067
}
5057-
return CG(current_import_const);
5068+
return ctx->imports_const;
50585069
EMPTY_SWITCH_DEFAULT_CASE()
50595070
}
50605071

@@ -5241,8 +5252,8 @@ void zend_compile_const_decl(zend_ast *ast) /* {{{ */
52415252
name = zend_prefix_with_ns(name);
52425253
name = zend_new_interned_string(name);
52435254

5244-
if (CG(current_import_const)
5245-
&& (import_name = zend_hash_find_ptr(CG(current_import_const), name))
5255+
if (CG(file_context).imports_const
5256+
&& (import_name = zend_hash_find_ptr(CG(file_context).imports_const, name))
52465257
) {
52475258
if (!zend_string_equals(import_name, name)) {
52485259
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "

Zend/zend_compile.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,26 @@
5353
typedef struct _zend_op_array zend_op_array;
5454
typedef struct _zend_op zend_op;
5555

56-
typedef struct _zend_compiler_context {
57-
uint32_t opcodes_size;
56+
/* Compilation context that is different for each op array. */
57+
typedef struct _zend_oparray_context {
58+
uint32_t opcodes_size;
5859
int vars_size;
5960
int literals_size;
6061
int current_brk_cont;
6162
int backpatch_count;
6263
int in_finally;
6364
uint32_t fast_call_var;
6465
HashTable *labels;
65-
} zend_compiler_context;
66+
} zend_oparray_context;
6667

67-
/* On 64-bi systems less optimal, but more compact VM code leads to better
68+
/* Compilation context that is different for each file, but shared between op arrays. */
69+
typedef struct _zend_file_context {
70+
HashTable *imports;
71+
HashTable *imports_function;
72+
HashTable *imports_const;
73+
} zend_file_context;
74+
75+
/* On 64-bit systems less optimal, but more compact VM code leads to better
6876
* performance. So on 32-bit systems we use absolute addresses for jump
6977
* targets and constants, but on 64-bit systems realtive 32-bit offsets */
7078
#if SIZEOF_SIZE_T == 4
@@ -637,7 +645,11 @@ BEGIN_EXTERN_C()
637645
void init_compiler(void);
638646
void shutdown_compiler(void);
639647
void zend_init_compiler_data_structures(void);
640-
void zend_init_compiler_context(void);
648+
649+
void zend_oparray_context_begin(zend_oparray_context *prev_context);
650+
void zend_oparray_context_end(zend_oparray_context *prev_context);
651+
void zend_file_context_begin(zend_file_context *prev_context);
652+
void zend_file_context_end(zend_file_context *prev_context);
641653

642654
extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
643655
extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename);
@@ -693,7 +705,6 @@ void zend_verify_namespace(void);
693705
void zend_do_end_compilation(void);
694706

695707
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2);
696-
void zend_release_labels(int temporary);
697708

698709
ZEND_API void function_add_ref(zend_function *function);
699710

Zend/zend_globals.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,13 @@ struct _zend_compiler_globals {
113113
uint32_t compiler_options; /* set of ZEND_COMPILE_* constants */
114114

115115
zend_string *current_namespace;
116-
HashTable *current_import;
117-
HashTable *current_import_function;
118-
HashTable *current_import_const;
119116
zend_bool in_namespace;
120117
zend_bool has_bracketed_namespaces;
121118

122119
HashTable const_filenames;
123120

124-
zend_compiler_context context;
125-
zend_stack context_stack;
121+
zend_oparray_context context;
122+
zend_file_context file_context;
126123

127124
zend_arena *arena;
128125

0 commit comments

Comments
 (0)