This source file includes following definitions.
- optimize_temporary_variables
1 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #define OP1_CONST_IS_CLASS 1
38 #define OP2_CONST_IS_CLASS 2
39 #define EXT_CONST_IS_CLASS 4
40 #define RESULT_IS_UNUSED 8
41
42 static const char op_const_means_class[256] = {
43
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
47
48 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2,
49
50 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 9, 1, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
59 };
60 #endif
61
62 #define GET_AVAILABLE_T() \
63 for (i = 0; i < T; i++) { \
64 if (!taken_T[i]) { \
65 break; \
66 } \
67 } \
68 taken_T[i] = 1; \
69 if (i > max) { \
70 max = i; \
71 }
72
73 static void optimize_temporary_variables(zend_op_array *op_array)
74 {
75 int T = op_array->T;
76 char *taken_T;
77 zend_op **start_of_T;
78 char *valid_T;
79 int *map_T;
80 zend_op *opline, *end;
81 int currT;
82 int i;
83 int max = -1;
84 int var_to_free = -1;
85
86 taken_T = (char *) emalloc(T);
87 start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *));
88 valid_T = (char *) emalloc(T);
89 map_T = (int *) emalloc(T * sizeof(int));
90
91 end = op_array->opcodes;
92 opline = &op_array->opcodes[op_array->last - 1];
93
94
95 while (opline >= end) {
96 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
97 if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
98 if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
99 start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
100 }
101 }
102 #else
103 if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
104 start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
105 }
106 #endif
107 opline--;
108 }
109
110 memset(valid_T, 0, T);
111 memset(taken_T, 0, T);
112
113 end = op_array->opcodes;
114 opline = &op_array->opcodes[op_array->last - 1];
115
116 while (opline >= end) {
117 if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
118 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
119 || ((op_const_means_class[opline->opcode] & OP1_CONST_IS_CLASS) && ZEND_OP1_TYPE(opline) == IS_CONST)
120 #endif
121 ) {
122 currT = VAR_NUM(ZEND_OP1(opline).var);
123 if (!valid_T[currT]) {
124 GET_AVAILABLE_T();
125 map_T[currT] = i;
126 valid_T[currT] = 1;
127 }
128 ZEND_OP1(opline).var = NUM_VAR(map_T[currT]);
129 }
130
131
132 if (opline->opcode == ZEND_OP_DATA &&
133 (opline-1)->opcode == ZEND_ASSIGN_DIM) {
134 opline--;
135 continue;
136 }
137
138 if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
139 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
140 || ((op_const_means_class[opline->opcode] & OP2_CONST_IS_CLASS) && ZEND_OP2_TYPE(opline) == IS_CONST)
141 #endif
142 ) {
143 currT = VAR_NUM(ZEND_OP2(opline).var);
144 if (!valid_T[currT]) {
145 GET_AVAILABLE_T();
146 map_T[currT] = i;
147 valid_T[currT] = 1;
148 }
149 ZEND_OP2(opline).var = NUM_VAR(map_T[currT]);
150 }
151
152 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
153 if ((op_const_means_class[opline->opcode] & EXT_CONST_IS_CLASS)) {
154 #else
155 if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
156 opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
157 #endif
158 currT = VAR_NUM(opline->extended_value);
159 if (!valid_T[currT]) {
160 GET_AVAILABLE_T();
161 map_T[currT] = i;
162 valid_T[currT] = 1;
163 }
164 opline->extended_value = NUM_VAR(map_T[currT]);
165 }
166
167
168 if (opline->opcode == ZEND_ASSIGN_DIM &&
169 (opline + 1)->opcode == ZEND_OP_DATA &&
170 ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) {
171 currT = VAR_NUM(ZEND_OP2(opline + 1).var);
172 GET_AVAILABLE_T();
173 map_T[currT] = i;
174 valid_T[currT] = 1;
175 taken_T[i] = 0;
176 ZEND_OP2(opline + 1).var = NUM_VAR(i);
177 var_to_free = i;
178 }
179
180 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
181 if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
182 if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
183 #else
184 if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
185 #endif
186 currT = VAR_NUM(ZEND_RESULT(opline).var);
187 if (valid_T[currT]) {
188 if (start_of_T[currT] == opline) {
189 taken_T[map_T[currT]] = 0;
190 }
191 ZEND_RESULT(opline).var = NUM_VAR(map_T[currT]);
192 } else {
193 GET_AVAILABLE_T();
194
195 if (RESULT_UNUSED(opline)) {
196 taken_T[i] = 0;
197 } else {
198
199 map_T[currT] = i;
200 valid_T[currT] = 1;
201 }
202 ZEND_RESULT(opline).var = NUM_VAR(i);
203 }
204 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
205 }
206 #endif
207 }
208
209 if (var_to_free >= 0) {
210 taken_T[var_to_free] = 0;
211 var_to_free = -1;
212 }
213
214 opline--;
215 }
216
217 efree(taken_T);
218 efree(start_of_T);
219 efree(valid_T);
220 efree(map_T);
221 op_array->T = max + 1;
222 }