Coverage Report

Created: 2026-09-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/Optimizer/escape_analysis.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend OPcache, Escape Analysis                                        |
4
   +----------------------------------------------------------------------+
5
   | Copyright © The PHP Group and Contributors.                          |
6
   +----------------------------------------------------------------------+
7
   | This source file is subject to the Modified BSD License that is      |
8
   | bundled with this package in the file LICENSE, and is available      |
9
   | through the World Wide Web at <https://www.php.net/license/>.        |
10
   |                                                                      |
11
   | SPDX-License-Identifier: BSD-3-Clause                                |
12
   +----------------------------------------------------------------------+
13
   | Authors: Dmitry Stogov <dmitry@php.net>                              |
14
   +----------------------------------------------------------------------+
15
*/
16
17
#include "Optimizer/zend_optimizer.h"
18
#include "Optimizer/zend_optimizer_internal.h"
19
#include "zend_bitset.h"
20
#include "zend_cfg.h"
21
#include "zend_ssa.h"
22
#include "zend_inference.h"
23
#include "zend_dump.h"
24
25
/*
26
 * T. Kotzmann and H. Mossenbock. Escape analysis  in the context of dynamic
27
 * compilation and deoptimization. In Proceedings of the International
28
 * Conference on Virtual Execution Environments, pages 111-120, Chicago,
29
 * June 2005
30
 */
31
32
static zend_always_inline void union_find_init(int *parent, int *size, int count) /* {{{ */
33
14.4k
{
34
14.4k
  int i;
35
36
548k
  for (i = 0; i < count; i++) {
37
533k
    parent[i] = i;
38
533k
    size[i] = 1;
39
533k
  }
40
14.4k
}
41
/* }}} */
42
43
static zend_always_inline int union_find_root(int *parent, int i) /* {{{ */
44
1.11M
{
45
1.11M
  int p = parent[i];
46
47
1.55M
  while (i != p) {
48
434k
    p = parent[p];
49
434k
    parent[i] = p;
50
434k
    i = p;
51
434k
    p = parent[i];
52
434k
  }
53
1.11M
  return i;
54
1.11M
}
55
/* }}} */
56
57
static zend_always_inline void union_find_unite(int *parent, int *size, int i, int j) /* {{{ */
58
291k
{
59
291k
  int r1 = union_find_root(parent, i);
60
291k
  int r2 = union_find_root(parent, j);
61
62
291k
  if (r1 != r2) {
63
209k
    if (size[r1] < size[r2]) {
64
99.2k
      parent[r1] = r2;
65
99.2k
      size[r2] += size[r1];
66
109k
    } else {
67
109k
      parent[r2] = r1;
68
109k
      size[r1] += size[r2];
69
109k
    }
70
209k
  }
71
291k
}
72
/* }}} */
73
74
static zend_result zend_build_equi_escape_sets(int *parent, const zend_op_array *op_array, const zend_ssa *ssa) /* {{{ */
75
14.4k
{
76
14.4k
  zend_ssa_var *ssa_vars = ssa->vars;
77
14.4k
  int ssa_vars_count = ssa->vars_count;
78
14.4k
  int i;
79
14.4k
  int *size;
80
14.4k
  ALLOCA_FLAG(use_heap)
81
82
14.4k
  size = do_alloca(sizeof(int) * ssa_vars_count, use_heap);
83
14.4k
  if (!size) {
84
0
    return FAILURE;
85
0
  }
86
14.4k
  union_find_init(parent, size, ssa_vars_count);
87
88
548k
  for (i = 0; i < ssa_vars_count; i++) {
89
533k
    if (ssa_vars[i].definition_phi) {
90
77.9k
      const zend_ssa_phi *p = ssa_vars[i].definition_phi;
91
77.9k
      if (p->pi >= 0) {
92
20.8k
        union_find_unite(parent, size, i, p->sources[0]);
93
57.0k
      } else {
94
176k
        for (uint32_t j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
95
119k
          union_find_unite(parent, size, i, p->sources[j]);
96
119k
        }
97
57.0k
      }
98
455k
    } else if (ssa_vars[i].definition >= 0) {
99
405k
      int def = ssa_vars[i].definition;
100
405k
      const zend_ssa_op *op = ssa->ops + def;
101
405k
      const zend_op *opline =  op_array->opcodes + def;
102
103
405k
      if (op->op1_def >= 0) {
104
103k
        if (op->op1_use >= 0) {
105
103k
          if (opline->opcode != ZEND_ASSIGN) {
106
52.2k
            union_find_unite(parent, size, op->op1_def, op->op1_use);
107
52.2k
          }
108
103k
        }
109
103k
        if (opline->opcode == ZEND_ASSIGN && op->op2_use >= 0) {
110
36.9k
          union_find_unite(parent, size, op->op1_def, op->op2_use);
111
36.9k
        }
112
103k
      }
113
405k
      if (op->op2_def >= 0) {
114
6.79k
        if (op->op2_use >= 0) {
115
6.40k
          union_find_unite(parent, size, op->op2_def, op->op2_use);
116
6.40k
        }
117
6.79k
      }
118
405k
      if (op->result_def >= 0) {
119
340k
        if (op->result_use >= 0) {
120
22.3k
          if (opline->opcode != ZEND_QM_ASSIGN) {
121
22.3k
            union_find_unite(parent, size, op->result_def, op->result_use);
122
22.3k
          }
123
22.3k
        }
124
340k
        if (opline->opcode == ZEND_QM_ASSIGN && op->op1_use >= 0) {
125
2.31k
          union_find_unite(parent, size, op->result_def, op->op1_use);
126
2.31k
        }
127
340k
        if (opline->opcode == ZEND_ASSIGN && op->op2_use >= 0) {
128
14.4k
          union_find_unite(parent, size, op->result_def, op->op2_use);
129
14.4k
        }
130
340k
        if (opline->opcode == ZEND_ASSIGN && op->op1_def >= 0) {
131
16.2k
          union_find_unite(parent, size, op->result_def, op->op1_def);
132
16.2k
        }
133
340k
      }
134
405k
    }
135
533k
  }
136
137
548k
  for (i = 0; i < ssa_vars_count; i++) {
138
533k
    parent[i] = union_find_root(parent, i);
139
533k
  }
140
141
14.4k
  free_alloca(size, use_heap);
142
143
14.4k
  return SUCCESS;
144
14.4k
}
145
/* }}} */
146
147
static bool is_allocation_def(const zend_op_array *op_array, const zend_ssa *ssa, int def, int var, const zend_script *script) /* {{{ */
148
312k
{
149
312k
  const zend_ssa_op *ssa_op = ssa->ops + def;
150
312k
  zend_op *opline = op_array->opcodes + def;
151
152
312k
  if (ssa_op->result_def == var) {
153
229k
    switch (opline->opcode) {
154
7.75k
      case ZEND_INIT_ARRAY:
155
7.75k
        return true;
156
29.4k
      case ZEND_NEW: {
157
          /* objects with destructors should escape */
158
29.4k
        const zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
159
29.4k
          script, op_array, opline);
160
29.4k
        uint32_t forbidden_flags =
161
          /* These flags will always cause an exception */
162
29.4k
          ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
163
29.4k
          | ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
164
29.4k
        if (ce
165
26.1k
         && !ce->parent
166
23.7k
         && !ce->create_object
167
18.3k
         && ce->default_object_handlers->get_constructor == zend_std_get_constructor
168
18.3k
         && ce->default_object_handlers->dtor_obj == zend_objects_destroy_object
169
18.3k
         && !ce->constructor
170
16.1k
         && !ce->destructor
171
14.6k
         && !ce->__get
172
14.0k
         && !ce->__set
173
13.8k
         && !(ce->ce_flags & forbidden_flags)
174
13.8k
         && (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
175
13.7k
          return true;
176
13.7k
        }
177
15.6k
        break;
178
29.4k
      }
179
15.6k
      case ZEND_QM_ASSIGN:
180
1.43k
        if (opline->op1_type == IS_CONST
181
34
         && Z_TYPE_P(CRT_CONSTANT(opline->op1)) == IS_ARRAY) {
182
34
          return true;
183
34
        }
184
1.39k
        if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_ARRAY)) {
185
471
          return true;
186
471
        }
187
928
        break;
188
928
      case ZEND_ASSIGN:
189
755
        if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_ARRAY)) {
190
308
          return true;
191
308
        }
192
447
        break;
193
229k
    }
194
229k
  } else if (ssa_op->op1_def == var) {
195
80.6k
    switch (opline->opcode) {
196
46.4k
      case ZEND_ASSIGN:
197
46.4k
        if (opline->op2_type == IS_CONST
198
21.7k
         && Z_TYPE_P(CRT_CONSTANT(opline->op2)) == IS_ARRAY) {
199
8.86k
          return true;
200
8.86k
        }
201
37.6k
        if (opline->op2_type == IS_CV && (OP2_INFO() & MAY_BE_ARRAY)) {
202
946
          return true;
203
946
        }
204
36.6k
        break;
205
36.6k
      case ZEND_ASSIGN_DIM:
206
4.05k
        if (OP1_INFO() & (MAY_BE_UNDEF | MAY_BE_NULL | MAY_BE_FALSE)) {
207
          /* implicit object/array allocation */
208
3.94k
          return true;
209
3.94k
        }
210
104
        break;
211
80.6k
    }
212
80.6k
  }
213
214
276k
  return false;
215
312k
}
216
/* }}} */
217
218
static bool is_local_def(const zend_op_array *op_array, const zend_ssa *ssa, int def, int var, const zend_script *script) /* {{{ */
219
163k
{
220
163k
  const zend_ssa_op *op = ssa->ops + def;
221
163k
  const zend_op *opline = op_array->opcodes + def;
222
223
163k
  if (op->result_def == var) {
224
122k
    switch (opline->opcode) {
225
5.18k
      case ZEND_INIT_ARRAY:
226
27.0k
      case ZEND_ADD_ARRAY_ELEMENT:
227
27.7k
      case ZEND_QM_ASSIGN:
228
28.6k
      case ZEND_ASSIGN:
229
28.6k
        return true;
230
13.1k
      case ZEND_NEW: {
231
        /* objects with destructors should escape */
232
13.1k
        const zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
233
13.1k
          script, op_array, opline);
234
13.1k
        if (ce
235
11.9k
         && !ce->create_object
236
9.98k
         && ce->default_object_handlers->get_constructor == zend_std_get_constructor
237
9.98k
         && ce->default_object_handlers->dtor_obj == zend_objects_destroy_object
238
9.98k
         && !ce->constructor
239
9.26k
         && !ce->destructor
240
8.97k
         && !ce->__get
241
8.89k
         && !ce->__set
242
8.89k
         && !ce->parent) {
243
8.59k
          return true;
244
8.59k
        }
245
4.56k
        break;
246
13.1k
      }
247
122k
    }
248
122k
  } else if (op->op1_def == var) {
249
38.0k
    switch (opline->opcode) {
250
18.5k
      case ZEND_ASSIGN:
251
24.9k
      case ZEND_ASSIGN_DIM:
252
27.7k
      case ZEND_ASSIGN_OBJ:
253
27.7k
      case ZEND_ASSIGN_OBJ_REF:
254
28.2k
      case ZEND_ASSIGN_DIM_OP:
255
28.3k
      case ZEND_ASSIGN_OBJ_OP:
256
28.5k
      case ZEND_PRE_INC_OBJ:
257
28.6k
      case ZEND_PRE_DEC_OBJ:
258
28.6k
      case ZEND_POST_INC_OBJ:
259
28.6k
      case ZEND_POST_DEC_OBJ:
260
28.6k
        return true;
261
38.0k
    }
262
38.0k
  }
263
264
97.9k
  return false;
265
163k
}
266
/* }}} */
267
268
static bool is_escape_use(const zend_op_array *op_array, const zend_ssa *ssa, int use, int var) /* {{{ */
269
33.3k
{
270
33.3k
  const zend_ssa_op *ssa_op = ssa->ops + use;
271
33.3k
  const zend_op *opline = op_array->opcodes + use;
272
273
33.3k
  if (ssa_op->op1_use == var) {
274
18.9k
    switch (opline->opcode) {
275
1.02k
      case ZEND_ASSIGN:
276
        /* no_val */
277
1.02k
        break;
278
267
      case ZEND_QM_ASSIGN:
279
267
        if (opline->op1_type == IS_CV) {
280
267
          if (OP1_INFO() & MAY_BE_OBJECT) {
281
            /* object aliasing */
282
253
            return true;
283
253
          }
284
267
        }
285
14
        break;
286
98
      case ZEND_ISSET_ISEMPTY_DIM_OBJ:
287
122
      case ZEND_ISSET_ISEMPTY_PROP_OBJ:
288
1.95k
      case ZEND_FETCH_DIM_R:
289
2.20k
      case ZEND_FETCH_OBJ_R:
290
2.88k
      case ZEND_FETCH_DIM_IS:
291
2.89k
      case ZEND_FETCH_OBJ_IS:
292
2.89k
        break;
293
2
      case ZEND_ASSIGN_OP:
294
2
        return true;
295
74
      case ZEND_ASSIGN_DIM_OP:
296
144
      case ZEND_ASSIGN_OBJ_OP:
297
144
      case ZEND_ASSIGN_STATIC_PROP_OP:
298
5.56k
      case ZEND_ASSIGN_DIM:
299
6.16k
      case ZEND_ASSIGN_OBJ:
300
6.18k
      case ZEND_ASSIGN_OBJ_REF:
301
6.18k
        break;
302
4
      case ZEND_PRE_INC_OBJ:
303
16
      case ZEND_PRE_DEC_OBJ:
304
18
      case ZEND_POST_INC_OBJ:
305
18
      case ZEND_POST_DEC_OBJ:
306
18
        break;
307
453
      case ZEND_INIT_ARRAY:
308
1.23k
      case ZEND_ADD_ARRAY_ELEMENT:
309
1.23k
        if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
310
0
          return true;
311
0
        }
312
1.23k
        if (OP1_INFO() & MAY_BE_OBJECT) {
313
          /* object aliasing */
314
769
          return true;
315
769
        }
316
        /* reference dependencies processed separately */
317
468
        break;
318
1.00k
      case ZEND_OP_DATA:
319
1.00k
        if ((opline-1)->opcode != ZEND_ASSIGN_DIM
320
759
         && (opline-1)->opcode != ZEND_ASSIGN_OBJ) {
321
102
          return true;
322
102
        }
323
906
        if (OP1_INFO() & MAY_BE_OBJECT) {
324
          /* object aliasing */
325
703
          return true;
326
703
        }
327
203
        opline--;
328
203
        ssa_op--;
329
203
        if (opline->op1_type != IS_CV
330
161
         || (OP1_INFO() & MAY_BE_REF)
331
159
         || (ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias)) {
332
          /* assignment into escaping structure */
333
159
          return true;
334
159
        }
335
        /* reference dependencies processed separately */
336
44
        break;
337
6.33k
      default:
338
6.33k
        return true;
339
18.9k
    }
340
18.9k
  }
341
342
25.0k
  if (ssa_op->op2_use == var) {
343
6.30k
    switch (opline->opcode) {
344
5.61k
      case ZEND_ASSIGN:
345
5.61k
        if (opline->op1_type != IS_CV
346
5.57k
         || (OP1_INFO() & MAY_BE_REF)
347
4.36k
         || (ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias)) {
348
          /* assignment into escaping variable */
349
4.36k
          return true;
350
4.36k
        }
351
1.24k
        if (opline->op2_type == IS_CV || opline->result_type != IS_UNUSED) {
352
253
          if (OP2_INFO() & MAY_BE_OBJECT) {
353
            /* object aliasing */
354
177
            return true;
355
177
          }
356
253
        }
357
1.06k
        break;
358
1.06k
      default:
359
699
        return true;
360
6.30k
    }
361
6.30k
  }
362
363
19.7k
  if (ssa_op->result_use == var) {
364
8.07k
    switch (opline->opcode) {
365
0
      case ZEND_ASSIGN:
366
0
      case ZEND_QM_ASSIGN:
367
0
      case ZEND_INIT_ARRAY:
368
8.07k
      case ZEND_ADD_ARRAY_ELEMENT:
369
8.07k
        break;
370
0
      default:
371
0
        return true;
372
8.07k
    }
373
8.07k
  }
374
375
19.7k
  return false;
376
19.7k
}
377
/* }}} */
378
379
zend_result zend_ssa_escape_analysis(const zend_script *script, const zend_op_array *op_array, const zend_ssa *ssa) /* {{{ */
380
90.1k
{
381
90.1k
  zend_ssa_var *ssa_vars = ssa->vars;
382
90.1k
  int ssa_vars_count = ssa->vars_count;
383
90.1k
  int i, root, use;
384
90.1k
  int *ees;
385
90.1k
  bool has_allocations;
386
90.1k
  int num_non_escaped;
387
90.1k
  ALLOCA_FLAG(use_heap)
388
389
90.1k
  if (!ssa_vars) {
390
0
    return SUCCESS;
391
0
  }
392
393
90.1k
  has_allocations = false;
394
961k
  for (i = op_array->last_var; i < ssa_vars_count; i++) {
395
885k
    if (ssa_vars[i].definition >= 0
396
772k
      && (ssa->var_info[i].type & (MAY_BE_ARRAY|MAY_BE_OBJECT))
397
285k
      && is_allocation_def(op_array, ssa, ssa_vars[i].definition, i, script)) {
398
14.4k
      has_allocations = true;
399
14.4k
      break;
400
14.4k
    }
401
885k
  }
402
90.1k
  if (!has_allocations) {
403
75.7k
    return SUCCESS;
404
75.7k
  }
405
406
407
  /* 1. Build EES (Equi-Escape Sets) */
408
14.4k
  ees = do_alloca(sizeof(int) * ssa_vars_count, use_heap);
409
14.4k
  if (!ees) {
410
0
    return FAILURE;
411
0
  }
412
413
14.4k
  if (zend_build_equi_escape_sets(ees, op_array, ssa) == FAILURE) {
414
0
    free_alloca(ees, use_heap);
415
0
    return FAILURE;
416
0
  }
417
418
  /* 2. Identify Allocations */
419
14.4k
  num_non_escaped = 0;
420
497k
  for (i = op_array->last_var; i < ssa_vars_count; i++) {
421
483k
    root = ees[i];
422
483k
    if (ssa_vars[root].escape_state > ESCAPE_STATE_NO_ESCAPE) {
423
      /* already escape. skip */
424
422k
    } else if (ssa_vars[i].alias && (ssa->var_info[i].type & MAY_BE_REF)) {
425
0
      if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
426
0
        num_non_escaped--;
427
0
      }
428
0
      ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
429
422k
    } else if (ssa_vars[i].definition >= 0
430
366k
       && (ssa->var_info[i].type & (MAY_BE_ARRAY|MAY_BE_OBJECT))) {
431
163k
      if (!is_local_def(op_array, ssa, ssa_vars[i].definition, i, script)) {
432
97.9k
        if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
433
4.33k
          num_non_escaped--;
434
4.33k
        }
435
97.9k
        ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
436
97.9k
      } else if (ssa_vars[root].escape_state == ESCAPE_STATE_UNKNOWN
437
27.8k
       && is_allocation_def(op_array, ssa, ssa_vars[i].definition, i, script)) {
438
21.6k
        ssa_vars[root].escape_state = ESCAPE_STATE_NO_ESCAPE;
439
21.6k
        num_non_escaped++;
440
21.6k
      }
441
163k
    }
442
483k
  }
443
444
  /* 3. Mark escaped EES */
445
14.4k
  if (num_non_escaped) {
446
307k
    for (i = 0; i < ssa_vars_count; i++) {
447
296k
      if (ssa_vars[i].use_chain >= 0) {
448
242k
        root = ees[i];
449
242k
        if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
450
63.9k
          FOREACH_USE(ssa_vars + i, use) {
451
63.9k
            if (is_escape_use(op_array, ssa, use, i)) {
452
13.5k
              ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
453
13.5k
              num_non_escaped--;
454
13.5k
              if (num_non_escaped == 0) {
455
8.02k
                i = ssa_vars_count;
456
8.02k
              }
457
13.5k
              break;
458
13.5k
            }
459
63.9k
          } FOREACH_USE_END();
460
30.6k
        }
461
242k
      }
462
296k
    }
463
10.6k
  }
464
465
  /* 4. Process referential dependencies */
466
14.4k
  if (num_non_escaped) {
467
2.63k
    bool changed;
468
469
2.66k
    do {
470
2.66k
      changed = false;
471
124k
      for (i = 0; i < ssa_vars_count; i++) {
472
121k
        if (ssa_vars[i].use_chain >= 0) {
473
96.4k
          root = ees[i];
474
96.4k
          if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
475
18.4k
            FOREACH_USE(ssa_vars + i, use) {
476
18.4k
              const zend_ssa_op *op = ssa->ops + use;
477
18.4k
              const zend_op *opline = op_array->opcodes + use;
478
18.4k
              int enclosing_root;
479
480
18.4k
              if (opline->opcode == ZEND_OP_DATA &&
481
32
                  ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
482
26
                   (opline-1)->opcode == ZEND_ASSIGN_OBJ ||
483
0
                   (opline-1)->opcode == ZEND_ASSIGN_OBJ_REF) &&
484
32
                  op->op1_use == i &&
485
32
                  (op-1)->op1_use >= 0) {
486
32
                enclosing_root = ees[(op-1)->op1_use];
487
10.1k
              } else if ((opline->opcode == ZEND_INIT_ARRAY ||
488
10.0k
                   opline->opcode == ZEND_ADD_ARRAY_ELEMENT) &&
489
1.96k
                  op->op1_use == i &&
490
766
                  op->result_def >= 0) {
491
766
                enclosing_root = ees[op->result_def];
492
9.42k
              } else {
493
9.42k
                continue;
494
9.42k
              }
495
496
798
              if (ssa_vars[enclosing_root].escape_state == ESCAPE_STATE_UNKNOWN ||
497
790
                  ssa_vars[enclosing_root].escape_state > ssa_vars[root].escape_state) {
498
466
                  if (ssa_vars[enclosing_root].escape_state == ESCAPE_STATE_UNKNOWN) {
499
8
                  ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
500
458
                  } else {
501
458
                  ssa_vars[root].escape_state = ssa_vars[enclosing_root].escape_state;
502
458
                }
503
466
                if (ssa_vars[root].escape_state == ESCAPE_STATE_GLOBAL_ESCAPE) {
504
466
                  num_non_escaped--;
505
466
                  if (num_non_escaped == 0) {
506
198
                    changed = false;
507
268
                  } else {
508
268
                    changed = true;
509
268
                  }
510
466
                  break;
511
466
                } else {
512
0
                  changed = true;
513
0
                }
514
466
              }
515
798
            } FOREACH_USE_END();
516
8.22k
          }
517
96.4k
        }
518
121k
      }
519
2.66k
    } while (changed);
520
2.63k
  }
521
522
  /* 5. Propagate values of escape sets to variables */
523
548k
  for (i = 0; i < ssa_vars_count; i++) {
524
533k
    root = ees[i];
525
533k
    if (i != root) {
526
209k
      ssa_vars[i].escape_state = ssa_vars[root].escape_state;
527
209k
    }
528
533k
  }
529
530
14.4k
  free_alloca(ees, use_heap);
531
532
14.4k
  return SUCCESS;
533
14.4k
}
534
/* }}} */