root/ext/opcache/Optimizer/compact_literals.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. optimizer_literal_obj_info
  2. optimizer_literal_class_info
  3. zend_optimizer_compact_literals

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend OPcache                                                         |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Dmitry Stogov <dmitry@zend.com>                             |
  16    |          Xinchen Hui <laruence@php.net>                              |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* pass 11
  21  * - compact literals table
  22  */
  23 
  24 #include "php.h"
  25 #include "Optimizer/zend_optimizer.h"
  26 #include "Optimizer/zend_optimizer_internal.h"
  27 #include "zend_API.h"
  28 #include "zend_constants.h"
  29 #include "zend_execute.h"
  30 #include "zend_vm.h"
  31 
  32 #define DEBUG_COMPACT_LITERALS 0
  33 
  34 #define LITERAL_VALUE                        0x0100
  35 #define LITERAL_FUNC                         0x0200
  36 #define LITERAL_CLASS                        0x0300
  37 #define LITERAL_CONST                        0x0400
  38 #define LITERAL_CLASS_CONST                  0x0500
  39 #define LITERAL_STATIC_METHOD                0x0600
  40 #define LITERAL_STATIC_PROPERTY              0x0700
  41 #define LITERAL_METHOD                       0x0800
  42 #define LITERAL_PROPERTY                     0x0900
  43 #define LITERAL_GLOBAL                       0x0A00
  44 
  45 #define LITERAL_EX_CLASS                     0x4000
  46 #define LITERAL_EX_OBJ                       0x2000
  47 #define LITERAL_MAY_MERGE                    0x1000
  48 #define LITERAL_KIND_MASK                    0x0f00
  49 #define LITERAL_NUM_RELATED_MASK             0x000f
  50 #define LITERAL_NUM_SLOTS_MASK               0x00f0
  51 #define LITERAL_NUM_SLOTS_SHIFT              4
  52 
  53 #define LITERAL_NUM_RELATED(info) (info & LITERAL_NUM_RELATED_MASK)
  54 #define LITERAL_NUM_SLOTS(info)   ((info & LITERAL_NUM_SLOTS_MASK) >> LITERAL_NUM_SLOTS_SHIFT)
  55 
  56 typedef struct _literal_info {
  57         uint32_t  flags; /* bitmask (see defines above) */
  58         union {
  59                 int    num;   /* variable number or class name literal number */
  60         } u;
  61 } literal_info;
  62 
  63 #define LITERAL_FLAGS(kind, slots, related) \
  64         ((kind) | ((slots) << LITERAL_NUM_SLOTS_SHIFT) | (related))
  65 
  66 #define LITERAL_INFO(n, kind, merge, slots, related) do { \
  67                 info[n].flags = (((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
  68         } while (0)
  69 
  70 #define LITERAL_INFO_CLASS(n, kind, merge, slots, related, _num) do { \
  71                 info[n].flags = (LITERAL_EX_CLASS | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
  72                 info[n].u.num = (_num); \
  73         } while (0)
  74 
  75 #define LITERAL_INFO_OBJ(n, kind, merge, slots, related, _num) do { \
  76                 info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
  77                 info[n].u.num = (_num); \
  78         } while (0)
  79 
  80 static void optimizer_literal_obj_info(literal_info   *info,
  81                                        zend_uchar      op_type,
  82                                        znode_op        op,
  83                                        int             constant,
  84                                        uint32_t       kind,
  85                                        uint32_t       slots,
  86                                        uint32_t       related,
  87                                        zend_op_array  *op_array)
  88 {
  89         /* For now we merge only $this object properties and methods.
  90          * In general it's also possible to do it for any CV variable as well,
  91          * but it would require complex dataflow and/or type analysis.
  92          */
  93         if (Z_TYPE(op_array->literals[constant]) == IS_STRING &&
  94             op_type == IS_UNUSED) {
  95                 LITERAL_INFO_OBJ(constant, kind, 1, slots, related, op_array->this_var);
  96         } else {
  97                 LITERAL_INFO(constant, kind, 0, slots, related);
  98         }
  99 }
 100 
 101 static void optimizer_literal_class_info(literal_info   *info,
 102                                          zend_uchar      op_type,
 103                                          znode_op        op,
 104                                          int             constant,
 105                                          uint32_t       kind,
 106                                          uint32_t       slots,
 107                                          uint32_t       related,
 108                                          zend_op_array  *op_array)
 109 {
 110         if (op_type == IS_CONST) {
 111                 LITERAL_INFO_CLASS(constant, kind, 1, slots, related, op.constant);
 112         } else {
 113                 LITERAL_INFO(constant, kind, 0, slots, related);
 114         }
 115 }
 116 
 117 void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
 118 {
 119         zend_op *opline, *end;
 120         int i, j, n, *map, cache_size;
 121         zval zv, *pos;
 122         literal_info *info;
 123         int l_null = -1;
 124         int l_false = -1;
 125         int l_true = -1;
 126         HashTable hash;
 127         zend_string *key = NULL;
 128         void *checkpoint = zend_arena_checkpoint(ctx->arena);
 129 
 130         if (op_array->last_literal) {
 131                 cache_size = 0;
 132                 info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
 133 
 134             /* Mark literals of specific types */
 135                 opline = op_array->opcodes;
 136                 end = opline + op_array->last;
 137                 while (opline < end) {
 138                         switch (opline->opcode) {
 139                                 case ZEND_INIT_FCALL:
 140                                         LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
 141                                         break;
 142                                 case ZEND_INIT_FCALL_BY_NAME:
 143                                         LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
 144                                         break;
 145                                 case ZEND_INIT_NS_FCALL_BY_NAME:
 146                                         LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3);
 147                                         break;
 148                                 case ZEND_INIT_METHOD_CALL:
 149                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 150                                                 optimizer_literal_obj_info(
 151                                                         info,
 152                                                         opline->op1_type,
 153                                                         opline->op1,
 154                                                         opline->op2.constant,
 155                                                         LITERAL_METHOD, 2, 2,
 156                                                         op_array);
 157                                         }
 158                                         break;
 159                                 case ZEND_INIT_STATIC_METHOD_CALL:
 160                                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 161                                                 LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
 162                                         }
 163                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 164                                                 optimizer_literal_class_info(
 165                                                         info,
 166                                                         opline->op1_type,
 167                                                         opline->op1,
 168                                                         opline->op2.constant,
 169                                                         LITERAL_STATIC_METHOD, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 2,
 170                                                         op_array);
 171                                         }
 172                                         break;
 173                                 case ZEND_CATCH:
 174                                         LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
 175                                         break;
 176                                 case ZEND_DEFINED:
 177                                         LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
 178                                         break;
 179                                 case ZEND_FETCH_CONSTANT:
 180                                         if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
 181                                                 if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
 182                                                         LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
 183                                                 } else {
 184                                                         LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
 185                                                 }
 186                                         } else {
 187                                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 188                                                         LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
 189                                                 }
 190                                                 optimizer_literal_class_info(
 191                                                         info,
 192                                                         opline->op1_type,
 193                                                         opline->op1,
 194                                                         opline->op2.constant,
 195                                                         LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
 196                                                         op_array);
 197                                         }
 198                                         break;
 199                                 case ZEND_FETCH_R:
 200                                 case ZEND_FETCH_W:
 201                                 case ZEND_FETCH_RW:
 202                                 case ZEND_FETCH_IS:
 203                                 case ZEND_FETCH_UNSET:
 204                                 case ZEND_FETCH_FUNC_ARG:
 205                                 case ZEND_UNSET_VAR:
 206                                 case ZEND_ISSET_ISEMPTY_VAR:
 207                                         if (ZEND_OP2_TYPE(opline) == IS_UNUSED) {
 208                                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 209                                                         LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
 210                                                 }
 211                                         } else {
 212                                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 213                                                         LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
 214                                                 }
 215                                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 216                                                         optimizer_literal_class_info(
 217                                                                 info,
 218                                                                 opline->op2_type,
 219                                                                 opline->op2,
 220                                                                 opline->op1.constant,
 221                                                                 LITERAL_STATIC_PROPERTY, 2, 1,
 222                                                                 op_array);
 223                                                 }
 224                                         }
 225                                         break;
 226                                 case ZEND_FETCH_CLASS:
 227                                 case ZEND_ADD_INTERFACE:
 228                                 case ZEND_ADD_TRAIT:
 229                                 case ZEND_INSTANCEOF:
 230                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 231                                                 LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
 232                                         }
 233                                         break;
 234                                 case ZEND_NEW:
 235                                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 236                                                 LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
 237                                         }
 238                                         break;
 239                                 case ZEND_ASSIGN_OBJ:
 240                                 case ZEND_FETCH_OBJ_R:
 241                                 case ZEND_FETCH_OBJ_W:
 242                                 case ZEND_FETCH_OBJ_RW:
 243                                 case ZEND_FETCH_OBJ_IS:
 244                                 case ZEND_FETCH_OBJ_UNSET:
 245                                 case ZEND_FETCH_OBJ_FUNC_ARG:
 246                                 case ZEND_UNSET_OBJ:
 247                                 case ZEND_PRE_INC_OBJ:
 248                                 case ZEND_PRE_DEC_OBJ:
 249                                 case ZEND_POST_INC_OBJ:
 250                                 case ZEND_POST_DEC_OBJ:
 251                                 case ZEND_ISSET_ISEMPTY_PROP_OBJ:
 252                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 253                                                 optimizer_literal_obj_info(
 254                                                         info,
 255                                                         opline->op1_type,
 256                                                         opline->op1,
 257                                                         opline->op2.constant,
 258                                                         LITERAL_PROPERTY, 2, 1,
 259                                                         op_array);
 260                                         }
 261                                         break;
 262                                 case ZEND_ASSIGN_ADD:
 263                                 case ZEND_ASSIGN_SUB:
 264                                 case ZEND_ASSIGN_MUL:
 265                                 case ZEND_ASSIGN_DIV:
 266                                 case ZEND_ASSIGN_POW:
 267                                 case ZEND_ASSIGN_MOD:
 268                                 case ZEND_ASSIGN_SL:
 269                                 case ZEND_ASSIGN_SR:
 270                                 case ZEND_ASSIGN_CONCAT:
 271                                 case ZEND_ASSIGN_BW_OR:
 272                                 case ZEND_ASSIGN_BW_AND:
 273                                 case ZEND_ASSIGN_BW_XOR:
 274                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 275                                                 if (opline->extended_value == ZEND_ASSIGN_OBJ) {
 276                                                         optimizer_literal_obj_info(
 277                                                                 info,
 278                                                                 opline->op1_type,
 279                                                                 opline->op1,
 280                                                                 opline->op2.constant,
 281                                                                 LITERAL_PROPERTY, 2, 1,
 282                                                                 op_array);
 283                                                 } else {
 284                                                         LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
 285                                                 }
 286                                         }
 287                                         break;
 288                                 case ZEND_BIND_GLOBAL:
 289                                         LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
 290                                         break;
 291                                 case ZEND_RECV_INIT:
 292                                         LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1);
 293                                         if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != -1) {
 294                                                 Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size;
 295                                                 cache_size += sizeof(void *);
 296                                         }
 297                                         break;
 298                                 case ZEND_RECV:
 299                                 case ZEND_RECV_VARIADIC:
 300                                 case ZEND_VERIFY_RETURN_TYPE:
 301                                         if (opline->op2.num != -1) {
 302                                                 opline->op2.num = cache_size;
 303                                                 cache_size += sizeof(void *);
 304                                         }
 305                                 default:
 306                                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 307                                                 LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
 308                                         }
 309                                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 310                                                 LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
 311                                         }
 312                                         break;
 313                         }
 314                         opline++;
 315                 }
 316 
 317 #if DEBUG_COMPACT_LITERALS
 318                 {
 319                         int i, use_copy;
 320                         fprintf(stderr, "File %s func %s\n", op_array->filename->val,
 321                                         op_array->function_name ? op_array->function_name->val : "main");
 322                         fprintf(stderr, "Literlas table size %d\n", op_array->last_literal);
 323 
 324                         for (i = 0; i < op_array->last_literal; i++) {
 325                                 zval zv;
 326                                 ZVAL_COPY_VALUE(&zv, op_array->literals + i);
 327                                 use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
 328                                 fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
 329                                 if (use_copy) {
 330                                         zval_dtor(&zv);
 331                                 }
 332                         }
 333                         fflush(stderr);
 334                 }
 335 #endif
 336 
 337                 /* Merge equal constants */
 338                 j = 0;
 339                 zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
 340                 map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
 341                 memset(map, 0, op_array->last_literal * sizeof(int));
 342                 for (i = 0; i < op_array->last_literal; i++) {
 343                         if (!info[i].flags) {
 344                                 /* unsed literal */
 345                                 zval_dtor(&op_array->literals[i]);
 346                                 continue;
 347                         }
 348                         switch (Z_TYPE(op_array->literals[i])) {
 349                                 case IS_NULL:
 350                                         /* Only checking MAY_MERGE for IS_NULL here 
 351                                          * is because only IS_NULL can be default value for class type hinting(RECV_INIT). */
 352                                         if ((info[i].flags & LITERAL_MAY_MERGE)) {
 353                                                 if (l_null < 0) {
 354                                                         l_null = j;
 355                                                         if (i != j) {
 356                                                                 op_array->literals[j] = op_array->literals[i];
 357                                                                 info[j] = info[i];
 358                                                         }
 359                                                         j++;
 360                                                 }
 361                                                 map[i] = l_null;
 362                                         } else {
 363                                                 map[i] = j;
 364                                                 if (i != j) {
 365                                                         op_array->literals[j] = op_array->literals[i];
 366                                                         info[j] = info[i];
 367                                                 }
 368                                                 j++;
 369                                         }
 370                                         break;
 371                                 case IS_FALSE:
 372                                         if (l_false < 0) {
 373                                                 l_false = j;
 374                                                 if (i != j) {
 375                                                         op_array->literals[j] = op_array->literals[i];
 376                                                         info[j] = info[i];
 377                                                 }
 378                                                 j++;
 379                                         }
 380                                         map[i] = l_false;
 381                                         break;
 382                                 case IS_TRUE:
 383                                         if (l_true < 0) {
 384                                                 l_true = j;
 385                                                 if (i != j) {
 386                                                         op_array->literals[j] = op_array->literals[i];
 387                                                         info[j] = info[i];
 388                                                 }
 389                                                 j++;
 390                                         }
 391                                         map[i] = l_true;
 392                                         break;
 393                                 case IS_LONG:
 394                                         if ((pos = zend_hash_index_find(&hash, Z_LVAL(op_array->literals[i]))) != NULL) {
 395                                                 map[i] = Z_LVAL_P(pos);
 396                                         } else {
 397                                                 map[i] = j;
 398                                                 ZVAL_LONG(&zv, j);
 399                                                 zend_hash_index_add_new(&hash, Z_LVAL(op_array->literals[i]), &zv);
 400                                                 if (i != j) {
 401                                                         op_array->literals[j] = op_array->literals[i];
 402                                                         info[j] = info[i];
 403                                                 }
 404                                                 j++;
 405                                         }
 406                                         break;
 407                                 case IS_DOUBLE:
 408                                         if ((pos = zend_hash_str_find(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
 409                                                 map[i] = Z_LVAL_P(pos);
 410                                         } else {
 411                                                 map[i] = j;
 412                                                 ZVAL_LONG(&zv, j);
 413                                                 zend_hash_str_add(&hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
 414                                                 if (i != j) {
 415                                                         op_array->literals[j] = op_array->literals[i];
 416                                                         info[j] = info[i];
 417                                                 }
 418                                                 j++;
 419                                         }
 420                                         break;
 421                                 case IS_STRING:
 422                                 case IS_CONSTANT:
 423                                         if (info[i].flags & LITERAL_MAY_MERGE) {
 424                                                 if (info[i].flags & LITERAL_EX_OBJ) {
 425                                                         int key_len = MAX_LENGTH_OF_LONG + sizeof("->") - 1 + Z_STRLEN(op_array->literals[i]);
 426                                                         key = zend_string_alloc(key_len, 0);
 427                                                         ZSTR_LEN(key) = snprintf(ZSTR_VAL(key), ZSTR_LEN(key)-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i]));
 428                                                 } else if (info[i].flags & LITERAL_EX_CLASS) {
 429                                                         int key_len;
 430                                                         zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];
 431                                                         key_len = Z_STRLEN_P(class_name) + sizeof("::") - 1 + Z_STRLEN(op_array->literals[i]);
 432                                                         key = zend_string_alloc(key_len, 0);
 433                                                         memcpy(ZSTR_VAL(key), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
 434                                                         memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
 435                                                         memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name) + sizeof("::") - 1,
 436                                                                 Z_STRVAL(op_array->literals[i]),
 437                                                                 Z_STRLEN(op_array->literals[i]) + 1);
 438                                                 } else {
 439                                                         key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
 440                                                 }
 441                                                 ZSTR_H(key) = zend_hash_func(ZSTR_VAL(key), ZSTR_LEN(key));
 442                                                 ZSTR_H(key) += info[i].flags;
 443                                         }
 444                                         if ((info[i].flags & LITERAL_MAY_MERGE) &&
 445                                                 (pos = zend_hash_find(&hash, key)) != NULL &&
 446                                                 Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) &&
 447                                                 info[i].flags == info[Z_LVAL_P(pos)].flags) {
 448 
 449                                                 zend_string_release(key);
 450                                                 map[i] = Z_LVAL_P(pos);
 451                                                 zval_dtor(&op_array->literals[i]);
 452                                                 n = LITERAL_NUM_RELATED(info[i].flags);
 453                                                 while (n > 1) {
 454                                                         i++;
 455                                                         zval_dtor(&op_array->literals[i]);
 456                                                         n--;
 457                                                 }
 458                                         } else {
 459                                                 map[i] = j;
 460                                                 if (info[i].flags & LITERAL_MAY_MERGE) {
 461                                                         ZVAL_LONG(&zv, j);
 462                                                         zend_hash_add_new(&hash, key, &zv);
 463                                                         zend_string_release(key);
 464                                                 }
 465                                                 if (i != j) {
 466                                                         op_array->literals[j] = op_array->literals[i];
 467                                                         info[j] = info[i];
 468                                                 }
 469                                                 if (LITERAL_NUM_SLOTS(info[i].flags)) {
 470                                                         Z_CACHE_SLOT(op_array->literals[j]) = cache_size;
 471                                                         cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*);
 472                                                 }
 473                                                 j++;
 474                                                 n = LITERAL_NUM_RELATED(info[i].flags);
 475                                                 while (n > 1) {
 476                                                         i++;
 477                                                         if (i != j) op_array->literals[j] = op_array->literals[i];
 478                                                         j++;
 479                                                         n--;
 480                                                 }
 481                                         }
 482                                         break;
 483                                 default:
 484                                         /* don't merge other types */
 485                                         map[i] = j;
 486                                         if (i != j) {
 487                                                 op_array->literals[j] = op_array->literals[i];
 488                                                 info[j] = info[i];
 489                                         }
 490                                         j++;
 491                                         break;
 492                         }
 493                 }
 494                 zend_hash_destroy(&hash);
 495                 op_array->last_literal = j;
 496                 op_array->cache_size = cache_size;
 497 
 498             /* Update opcodes to use new literals table */
 499                 opline = op_array->opcodes;
 500                 end = opline + op_array->last;
 501                 while (opline < end) {
 502                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 503                                 opline->op1.constant = map[opline->op1.constant];
 504                         }
 505                         if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 506                                 opline->op2.constant = map[opline->op2.constant];
 507                         }
 508                         opline++;
 509                 }
 510                 zend_arena_release(&ctx->arena, checkpoint);
 511 
 512 #if DEBUG_COMPACT_LITERALS
 513                 {
 514                         int i, use_copy;
 515                         fprintf(stderr, "Optimized literlas table size %d\n", op_array->last_literal);
 516 
 517                         for (i = 0; i < op_array->last_literal; i++) {
 518                                 zval zv;
 519                                 ZVAL_COPY_VALUE(&zv, op_array->literals + i);
 520                                 use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
 521                                 fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
 522                                 if (use_copy) {
 523                                         zval_dtor(&zv);
 524                                 }
 525                         }
 526                         fflush(stderr);
 527                 }
 528 #endif
 529         }
 530 }

/* [<][>][^][v][top][bottom][index][help] */