static void zend_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline, *end; /* Revert pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op1); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2); } opline++; } /* Do actual optimizations */ zend_optimize(op_array, ctx); /* Redo pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); } ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; } }
static PHP_METHOD(Operand, getNumber) { php_inspector_operand_t *operand = php_inspector_operand_this(); php_inspector_opline_t *opline = php_inspector_opline_fetch_from(Z_OBJ(operand->opline)); php_inspector_scope_t *scope = php_inspector_scope_fetch_from(Z_OBJ(opline->scope)); switch(opline->opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: if (operand->which == PHP_INSPECTOR_OPLINE_OP1) { ZEND_PASS_TWO_UNDO_JMP_TARGET(scope->ops, opline->opline, *operand->op); ZVAL_LONG(return_value, operand->op->num); ZEND_PASS_TWO_UPDATE_JMP_TARGET(scope->ops, opline->opline, *operand->op); break; } case ZEND_JMPZNZ: case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_NEW: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_ASSERT_CHECK: if (operand->which == PHP_INSPECTOR_OPLINE_OP2) { ZEND_PASS_TWO_UNDO_JMP_TARGET(scope->ops, opline->opline, *operand->op); ZVAL_LONG(return_value, operand->op->num); ZEND_PASS_TWO_UPDATE_JMP_TARGET(scope->ops, opline->opline, *operand->op); break; } default: { if (operand->type & IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(scope->ops, *operand->op); ZVAL_LONG(return_value, operand->op->num); ZEND_PASS_TWO_UPDATE_CONSTANT(scope->ops, *operand->op); } else if (operand->type & IS_TMP_VAR|IS_VAR) { ZVAL_LONG(return_value, EX_VAR_TO_NUM(operand->op->num - scope->ops->last_var)); } else if (operand->type & IS_CV) { ZVAL_LONG(return_value, EX_VAR_TO_NUM(operand->op->num)); } } } }
static PHP_METHOD(Operand, getValue) { php_inspector_operand_t *operand = php_inspector_operand_this(); if (operand->type & IS_CONST) { php_inspector_opline_t *opline = php_inspector_opline_fetch_from(Z_OBJ(operand->opline)); php_inspector_scope_t *scope = php_inspector_scope_fetch_from(Z_OBJ(opline->scope)); ZEND_PASS_TWO_UNDO_CONSTANT(scope->ops, *operand->op); ZVAL_COPY(return_value, &scope->ops->literals[operand->op->num]); ZEND_PASS_TWO_UPDATE_CONSTANT(scope->ops, *operand->op); } }
static void zend_accel_optimize(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline, *end; /* Revert pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op1); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2); } switch (opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline)); break; case ZEND_JMPZNZ: /* relative offset into absolute index */ opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value); /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_NEW: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_ASSERT_CHECK: ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP2(opline)); break; case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value); break; } opline++; } /* Do actual optimizations */ zend_optimize(op_array, ctx); /* Redo pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); } switch (opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline)); break; case ZEND_JMPZNZ: /* absolute index to relative offset */ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_NEW: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_ASSERT_CHECK: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP2(opline)); break; case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; } ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; } }
static void zend_file_cache_serialize_op_array(zend_op_array *op_array, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf) { if (op_array->static_variables && !IS_SERIALIZED(op_array->static_variables)) { HashTable *ht; SERIALIZE_PTR(op_array->static_variables); ht = op_array->static_variables; UNSERIALIZE_PTR(ht); zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); } if (op_array->scope && !IS_SERIALIZED(op_array->opcodes)) { if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) { op_array->refcount = (uint32_t*)(intptr_t)-1; SERIALIZE_PTR(op_array->literals); SERIALIZE_PTR(op_array->opcodes); SERIALIZE_PTR(op_array->arg_info); SERIALIZE_PTR(op_array->vars); SERIALIZE_STR(op_array->function_name); SERIALIZE_STR(op_array->filename); SERIALIZE_PTR(op_array->live_range); SERIALIZE_PTR(op_array->scope); SERIALIZE_STR(op_array->doc_comment); SERIALIZE_PTR(op_array->try_catch_array); SERIALIZE_PTR(op_array->prototype); return; } zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes); } if (op_array->literals && !IS_SERIALIZED(op_array->literals)) { zval *p, *end; SERIALIZE_PTR(op_array->literals); p = op_array->literals; UNSERIALIZE_PTR(p); end = p + op_array->last_literal; while (p < end) { zend_file_cache_serialize_zval(p, script, info, buf); p++; } } if (!IS_SERIALIZED(op_array->opcodes)) { zend_op *opline, *end; SERIALIZE_PTR(op_array->opcodes); opline = op_array->opcodes; UNSERIALIZE_PTR(opline); end = opline + op_array->last; while (opline < end) { #if ZEND_USE_ABS_CONST_ADDR if (opline->op1_type == IS_CONST) { SERIALIZE_PTR(opline->op1.zv); } if (opline->op2_type == IS_CONST) { SERIALIZE_PTR(opline->op2.zv); } #else if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline, opline->op1); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline, opline->op2); } #endif #if ZEND_USE_ABS_JMP_ADDR switch (opline->opcode) { case ZEND_JMP: case ZEND_FAST_CALL: SERIALIZE_PTR(opline->op1.jmp_addr); break; case ZEND_JMPZNZ: /* relative extended_value don't have to be changed */ /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_ASSERT_CHECK: SERIALIZE_PTR(opline->op2.jmp_addr); break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_SWITCH_LONG: case ZEND_SWITCH_STRING: /* relative extended_value don't have to be changed */ break; } #endif zend_serialize_opcode_handler(opline); opline++; } if (op_array->arg_info) { zend_arg_info *p, *end; SERIALIZE_PTR(op_array->arg_info); p = op_array->arg_info; UNSERIALIZE_PTR(p); end = p + op_array->num_args; if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { p--; } if (op_array->fn_flags & ZEND_ACC_VARIADIC) { end++; } while (p < end) { if (!IS_SERIALIZED(p->name)) { SERIALIZE_STR(p->name); } if (ZEND_TYPE_IS_CLASS(p->type)) { zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(p->type); zend_string *type_name = ZEND_TYPE_NAME(p->type); SERIALIZE_STR(type_name); p->type = (Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */ (allow_null ? (Z_UL(1) << (sizeof(zend_type)*8-2)) : Z_UL(0)) | /* type allow null */ (zend_type)type_name; } p++; } } if (op_array->vars) { zend_string **p, **end; SERIALIZE_PTR(op_array->vars); p = op_array->vars; UNSERIALIZE_PTR(p); end = p + op_array->last_var; while (p < end) { if (!IS_SERIALIZED(*p)) { SERIALIZE_STR(*p); } p++; } } SERIALIZE_STR(op_array->function_name); SERIALIZE_STR(op_array->filename); SERIALIZE_PTR(op_array->live_range); SERIALIZE_PTR(op_array->scope); SERIALIZE_STR(op_array->doc_comment); SERIALIZE_PTR(op_array->try_catch_array); SERIALIZE_PTR(op_array->prototype); } }