pass2.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /* pass 2:
  2. * - convert non-numeric constants to numeric constants in numeric operators
  3. * - optimize constant conditional JMPs
  4. * - optimize static BRKs and CONTs
  5. */
  6. if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
  7. zend_op *opline;
  8. zend_op *end = op_array->opcodes + op_array->last;
  9. opline = op_array->opcodes;
  10. while (opline < end) {
  11. switch (opline->opcode) {
  12. case ZEND_ADD:
  13. case ZEND_SUB:
  14. case ZEND_MUL:
  15. case ZEND_DIV:
  16. if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  17. if (ZEND_OP1_LITERAL(opline).type == IS_STRING) {
  18. convert_scalar_to_number(&ZEND_OP1_LITERAL(opline) TSRMLS_CC);
  19. }
  20. }
  21. /* break missing *intentionally* - the assign_op's may only optimize op2 */
  22. case ZEND_ASSIGN_ADD:
  23. case ZEND_ASSIGN_SUB:
  24. case ZEND_ASSIGN_MUL:
  25. case ZEND_ASSIGN_DIV:
  26. if (opline->extended_value != 0) {
  27. /* object tristate op - don't attempt to optimize it! */
  28. break;
  29. }
  30. if (ZEND_OP2_TYPE(opline) == IS_CONST) {
  31. if (ZEND_OP2_LITERAL(opline).type == IS_STRING) {
  32. convert_scalar_to_number(&ZEND_OP2_LITERAL(opline) TSRMLS_CC);
  33. }
  34. }
  35. break;
  36. case ZEND_MOD:
  37. case ZEND_SL:
  38. case ZEND_SR:
  39. if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  40. if (ZEND_OP1_LITERAL(opline).type != IS_LONG) {
  41. convert_to_long(&ZEND_OP1_LITERAL(opline));
  42. }
  43. }
  44. /* break missing *intentionally - the assign_op's may only optimize op2 */
  45. case ZEND_ASSIGN_MOD:
  46. case ZEND_ASSIGN_SL:
  47. case ZEND_ASSIGN_SR:
  48. if (opline->extended_value != 0) {
  49. /* object tristate op - don't attempt to optimize it! */
  50. break;
  51. }
  52. if (ZEND_OP2_TYPE(opline) == IS_CONST) {
  53. if (ZEND_OP2_LITERAL(opline).type != IS_LONG) {
  54. convert_to_long(&ZEND_OP2_LITERAL(opline));
  55. }
  56. }
  57. break;
  58. case ZEND_CONCAT:
  59. if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  60. if (ZEND_OP1_LITERAL(opline).type != IS_STRING) {
  61. convert_to_string(&ZEND_OP1_LITERAL(opline));
  62. }
  63. }
  64. /* break missing *intentionally - the assign_op's may only optimize op2 */
  65. case ZEND_ASSIGN_CONCAT:
  66. if (opline->extended_value != 0) {
  67. /* object tristate op - don't attempt to optimize it! */
  68. break;
  69. }
  70. if (ZEND_OP2_TYPE(opline) == IS_CONST) {
  71. if (ZEND_OP2_LITERAL(opline).type != IS_STRING) {
  72. convert_to_string(&ZEND_OP2_LITERAL(opline));
  73. }
  74. }
  75. break;
  76. case ZEND_JMPZ_EX:
  77. case ZEND_JMPNZ_EX:
  78. /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
  79. if (0 && /* FIXME: temporary disable unsafe pattern */
  80. ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
  81. ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
  82. ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
  83. opline->opcode -= 3;
  84. /* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
  85. in case we know it wouldn't jump */
  86. } else if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  87. int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
  88. if (opline->opcode == ZEND_JMPZ_EX) {
  89. should_jmp = !should_jmp;
  90. }
  91. if (!should_jmp) {
  92. opline->opcode = ZEND_QM_ASSIGN;
  93. SET_UNUSED(opline->op2);
  94. }
  95. }
  96. break;
  97. case ZEND_JMPZ:
  98. case ZEND_JMPNZ:
  99. if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  100. int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
  101. if (opline->opcode == ZEND_JMPZ) {
  102. should_jmp = !should_jmp;
  103. }
  104. literal_dtor(&ZEND_OP1_LITERAL(opline));
  105. ZEND_OP1_TYPE(opline) = IS_UNUSED;
  106. if (should_jmp) {
  107. opline->opcode = ZEND_JMP;
  108. COPY_NODE(opline->op1, opline->op2);
  109. } else {
  110. MAKE_NOP(opline);
  111. }
  112. break;
  113. }
  114. if ((opline + 1)->opcode == ZEND_JMP) {
  115. /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
  116. /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
  117. if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) {
  118. /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
  119. MAKE_NOP(opline);
  120. } else {
  121. if (opline->opcode == ZEND_JMPZ) {
  122. opline->extended_value = ZEND_OP1(opline + 1).opline_num;
  123. } else {
  124. opline->extended_value = ZEND_OP2(opline).opline_num;
  125. COPY_NODE(opline->op2, (opline + 1)->op1);
  126. }
  127. opline->opcode = ZEND_JMPZNZ;
  128. }
  129. }
  130. break;
  131. case ZEND_JMPZNZ:
  132. if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  133. int opline_num;
  134. if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
  135. opline_num = opline->extended_value; /* JMPNZ */
  136. } else {
  137. opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */
  138. }
  139. literal_dtor(&ZEND_OP1_LITERAL(opline));
  140. ZEND_OP1(opline).opline_num = opline_num;
  141. ZEND_OP1_TYPE(opline) = IS_UNUSED;
  142. opline->opcode = ZEND_JMP;
  143. }
  144. break;
  145. case ZEND_BRK:
  146. case ZEND_CONT:
  147. {
  148. zend_brk_cont_element *jmp_to;
  149. int array_offset;
  150. int nest_levels;
  151. int dont_optimize = 0;
  152. if (ZEND_OP2_TYPE(opline) != IS_CONST) {
  153. break;
  154. }
  155. convert_to_long(&ZEND_OP2_LITERAL(opline));
  156. nest_levels = ZEND_OP2_LITERAL(opline).value.lval;
  157. array_offset = ZEND_OP1(opline).opline_num;
  158. while (1) {
  159. if (array_offset == -1) {
  160. dont_optimize = 1; /* don't optimize this bogus break/continue, let the executor shout */
  161. break;
  162. }
  163. jmp_to = &op_array->brk_cont_array[array_offset];
  164. array_offset = jmp_to->parent;
  165. if (--nest_levels > 0) {
  166. if (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE ||
  167. op_array->opcodes[jmp_to->brk].opcode == ZEND_SWITCH_FREE
  168. ) {
  169. dont_optimize = 1;
  170. break;
  171. }
  172. } else {
  173. break;
  174. }
  175. }
  176. if (dont_optimize) {
  177. break;
  178. }
  179. /* optimize - convert to a JMP */
  180. switch (opline->opcode) {
  181. case ZEND_BRK:
  182. MAKE_NOP(opline);
  183. ZEND_OP1(opline).opline_num = jmp_to->brk;
  184. break;
  185. case ZEND_CONT:
  186. MAKE_NOP(opline);
  187. ZEND_OP1(opline).opline_num = jmp_to->cont;
  188. break;
  189. }
  190. opline->opcode = ZEND_JMP;
  191. /* MAKE_NOP() already set op1 and op2 to IS_UNUSED */
  192. }
  193. break;
  194. }
  195. opline++;
  196. }
  197. }