123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- /* ops that use CLs:
- op1:
- ZEND_FETCH_CONSTANT:
- ZEND_INIT_CTOR_CALL:
- ZEND_INIT_STATIC_METHOD_CALL:
- ZEND_INIT_METHOD_CALL:
- ZEND_IMPORT_CLASS:
- ZEND_IMPORT_FUNCTION:
- ZEND_IMPORT_CONST:
- ZEND_ADD_INTERFACE:
- ZEND_VERIFY_ABSTRACT_CLASS:
- ZEND_NEW:
- ZEND_CATCH:
- ZEND_INIT_FCALL_BY_NAME:
- op2:
- ZEND_UNSET_VAR:
- ZEND_ISSET_ISEMPTY_VAR:
- ZEND_FETCH_UNSET:
- ZEND_FETCH_IS:
- ZEND_FETCH_R:
- ZEND_FETCH_W:
- ZEND_FETCH_RW:
- ZEND_FETCH_FUNC_ARG:
- ZEND_ADD_INTERFACE:
- ZEND_INSTANCEOF:
- extended_value:
- ZEND_DECLARE_INHERITED_CLASS:
- ignore result
- INIT_METHOD_CALL:
- */
- #define OP1_CONST_IS_CLASS 1
- #define OP2_CONST_IS_CLASS 2
- #define EXT_CONST_IS_CLASS 4
- #define RESULT_IS_UNUSED 8
- static const char op_const_means_class[256] = {
- /* 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, 0,
- /* 32 */
- 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,
- /* 64 */
- 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,
- /* 96 */
- 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,
- /* 128 */
- 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,
- /* 160 */
- 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,
- /* 192 */
- 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,
- /* 224 */
- 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
- };
- #endif
- #define GET_AVAILABLE_T() \
- for (i = 0; i < T; i++) { \
- if (!taken_T[i]) { \
- break; \
- } \
- } \
- taken_T[i] = 1; \
- if (i > max) { \
- max = i; \
- }
- static void optimize_temporary_variables(zend_op_array *op_array)
- {
- int T = op_array->T;
- char *taken_T; /* T index in use */
- zend_op **start_of_T; /* opline where T is first used */
- char *valid_T; /* Is the map_T valid */
- int *map_T; /* Map's the T to its new index */
- zend_op *opline, *end;
- int currT;
- int i;
- int max = -1;
- int var_to_free = -1;
- taken_T = (char *) emalloc(T);
- start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *));
- valid_T = (char *) emalloc(T);
- map_T = (int *) emalloc(T * sizeof(int));
- end = op_array->opcodes;
- opline = &op_array->opcodes[op_array->last - 1];
- /* Find T definition points */
- while (opline >= end) {
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
- if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
- start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
- }
- }
- #else
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
- start_of_T[VAR_NUM(ZEND_RESULT(opline).var)] = opline;
- }
- #endif
- opline--;
- }
- memset(valid_T, 0, T);
- memset(taken_T, 0, T);
- end = op_array->opcodes;
- opline = &op_array->opcodes[op_array->last - 1];
- while (opline >= end) {
- if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- || ((op_const_means_class[opline->opcode] & OP1_CONST_IS_CLASS) && ZEND_OP1_TYPE(opline) == IS_CONST)
- #endif
- ) {
- currT = VAR_NUM(ZEND_OP1(opline).var);
- if (!valid_T[currT]) {
- GET_AVAILABLE_T();
- map_T[currT] = i;
- valid_T[currT] = 1;
- }
- ZEND_OP1(opline).var = NUM_VAR(map_T[currT]);
- }
- /* Skip OP_DATA */
- if (opline->opcode == ZEND_OP_DATA &&
- (opline-1)->opcode == ZEND_ASSIGN_DIM) {
- opline--;
- continue;
- }
- if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- || ((op_const_means_class[opline->opcode] & OP2_CONST_IS_CLASS) && ZEND_OP2_TYPE(opline) == IS_CONST)
- #endif
- ) {
- currT = VAR_NUM(ZEND_OP2(opline).var);
- if (!valid_T[currT]) {
- GET_AVAILABLE_T();
- map_T[currT] = i;
- valid_T[currT] = 1;
- }
- ZEND_OP2(opline).var = NUM_VAR(map_T[currT]);
- }
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if ((op_const_means_class[opline->opcode] & EXT_CONST_IS_CLASS)) {
- #else
- if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
- opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
- #endif
- currT = VAR_NUM(opline->extended_value);
- if (!valid_T[currT]) {
- GET_AVAILABLE_T();
- map_T[currT] = i;
- valid_T[currT] = 1;
- }
- opline->extended_value = NUM_VAR(map_T[currT]);
- }
- /* Allocate OP_DATA->op2 after "operands", but before "result" */
- if (opline->opcode == ZEND_ASSIGN_DIM &&
- (opline + 1)->opcode == ZEND_OP_DATA &&
- ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) {
- currT = VAR_NUM(ZEND_OP2(opline + 1).var);
- GET_AVAILABLE_T();
- map_T[currT] = i;
- valid_T[currT] = 1;
- taken_T[i] = 0;
- ZEND_OP2(opline + 1).var = NUM_VAR(i);
- var_to_free = i;
- }
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR | IS_CONST)) {
- if (!(op_const_means_class[opline->opcode] & RESULT_IS_UNUSED)) {
- #else
- if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
- #endif
- currT = VAR_NUM(ZEND_RESULT(opline).var);
- if (valid_T[currT]) {
- if (start_of_T[currT] == opline) {
- taken_T[map_T[currT]] = 0;
- }
- ZEND_RESULT(opline).var = NUM_VAR(map_T[currT]);
- } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */
- GET_AVAILABLE_T();
- if (RESULT_UNUSED(opline)) {
- taken_T[i] = 0;
- } else {
- /* Code which gets here is using a wrongly built opcode such as RECV() */
- map_T[currT] = i;
- valid_T[currT] = 1;
- }
- ZEND_RESULT(opline).var = NUM_VAR(i);
- }
- #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
- }
- #endif
- }
- if (var_to_free >= 0) {
- taken_T[var_to_free] = 0;
- var_to_free = -1;
- }
- opline--;
- }
- efree(taken_T);
- efree(start_of_T);
- efree(valid_T);
- efree(map_T);
- op_array->T = max + 1;
- }
|