Skip to content

Commit

Permalink
- MF20: Improve code coverage gathering performace by 1000%.
Browse files Browse the repository at this point in the history
SVN Rev: 2535
  • Loading branch information
derickr committed Oct 11, 2007
1 parent b22ffad commit 9e76e80
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 19 deletions.
2 changes: 1 addition & 1 deletion php_xdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ ZEND_BEGIN_MODULE_GLOBALS(xdebug)
xdebug_hash *code_coverage;
zend_bool code_coverage_unused;
zend_bool code_coverage_dead_code_analysis;
xdebug_hash *code_coverage_op_array_cache;
unsigned int function_count;
int reserved_offset;

/* used for collection errors */
zend_bool do_collect_errors;
Expand Down
15 changes: 11 additions & 4 deletions xdebug.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ XDEBUG_OPCODE_OVERRIDE(concat)

PHP_MINIT_FUNCTION(xdebug)
{
zend_extension dummy_ext;

ZEND_INIT_MODULE_GLOBALS(xdebug, php_xdebug_init_globals, php_xdebug_shutdown_globals);
REGISTER_INI_ENTRIES();
#if 0
Expand Down Expand Up @@ -570,6 +572,9 @@ PHP_MINIT_FUNCTION(xdebug)
new_error_cb = xdebug_error_cb;

#ifdef ZEND_ENGINE_2
/* Get reserved offset */
XG(reserved_offset) = zend_get_resource_handle(&dummy_ext);

/* Overload the "exit" opcode */
XDEBUG_SET_OPCODE_OVERRIDE(exit, ZEND_EXIT);
XDEBUG_SET_OPCODE_OVERRIDE(jmp, ZEND_JMP);
Expand Down Expand Up @@ -728,7 +733,6 @@ PHP_RINIT_FUNCTION(xdebug)
XG(do_trace) = 0;
XG(do_code_coverage) = 0;
XG(code_coverage) = xdebug_hash_alloc(32, xdebug_coverage_file_dtor);
XG(code_coverage_op_array_cache) = xdebug_hash_alloc(1024, NULL);
XG(stack) = xdebug_llist_alloc(xdebug_stack_element_dtor);
XG(trace_file) = NULL;
XG(tracefile_name) = NULL;
Expand Down Expand Up @@ -861,7 +865,6 @@ PHP_RSHUTDOWN_FUNCTION(xdebug)
XG(do_code_coverage) = 0;

xdebug_hash_destroy(XG(code_coverage));
xdebug_hash_destroy(XG(code_coverage_op_array_cache));

if (XG(context.list.last_file)) {
xdfree(XG(context).list.last_file);
Expand Down Expand Up @@ -1508,7 +1511,7 @@ void xdebug_execute(zend_op_array *op_array TSRMLS_DC)
}

if (XG(do_code_coverage) && XG(code_coverage_unused)) {
xdebug_prefill_code_coverage(fse, op_array TSRMLS_CC);
xdebug_prefill_code_coverage(op_array TSRMLS_CC);
}

/* If we're in an eval, we need to create an ID for it. This ID however
Expand Down Expand Up @@ -2421,7 +2424,11 @@ zend_op_array *xdebug_compile_file(zend_file_handle *file_handle, int type TSRML
zend_op_array *op_array;

op_array = old_compile_file(file_handle, type TSRMLS_CC);

op_array->reserved[XG(reserved_offset)] = 0;

if (XG(do_code_coverage) && XG(code_coverage_unused)) {
xdebug_prefill_code_coverage(op_array TSRMLS_CC);
}
return op_array;
}
/* }}} */
Expand Down
28 changes: 15 additions & 13 deletions xdebug_code_coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void xdebug_count_line(char *filename, int lineno, int executable, int deadcode
xdfree(sline);
}

static void prefill_from_opcode(function_stack_entry *fse, char *fn, zend_op opcode, int deadcode TSRMLS_DC)
static void prefill_from_opcode(char *fn, zend_op opcode, int deadcode TSRMLS_DC)
{
if (
opcode.opcode != ZEND_NOP &&
Expand Down Expand Up @@ -220,19 +220,16 @@ static void xdebug_analyse_branch(zend_op_array *opa, unsigned int position, xde
xdebug_set_add(set, position);
}
}
static void prefill_from_oparray(function_stack_entry *fse, char *fn, zend_op_array *opa TSRMLS_DC)

static void prefill_from_oparray(char *fn, zend_op_array *opa TSRMLS_DC)
{
char cache_key[256];
int cache_key_len;
void *dummy;
unsigned int i;
xdebug_set *set = NULL;

cache_key_len = snprintf(cache_key, sizeof(cache_key) - 1, "%p", opa->opcodes);
if (xdebug_hash_find(XG(code_coverage_op_array_cache), cache_key, cache_key_len, (void*) &dummy)) {
return;
}
xdebug_hash_add(XG(code_coverage_op_array_cache), cache_key, cache_key_len, NULL);
opa->reserved[XG(reserved_offset)] = 1;

#ifdef ZEND_ENGINE_2
/* Check for abstract methods and simply return from this function in those
Expand All @@ -252,7 +249,7 @@ static void prefill_from_oparray(function_stack_entry *fse, char *fn, zend_op_ar
/* The normal loop then finally */
for (i = 0; i < opa->size; i++) {
zend_op opcode = opa->opcodes[i];
prefill_from_opcode(NULL, fn, opcode, set ? !xdebug_set_in(set, i) : 0 TSRMLS_CC);
prefill_from_opcode(fn, opcode, set ? !xdebug_set_in(set, i) : 0 TSRMLS_CC);
}

if (set) {
Expand All @@ -267,8 +264,8 @@ static int prefill_from_function_table(zend_op_array *opa, int num_args, va_list

new_filename = va_arg(args, char*);
if (opa->type == ZEND_USER_FUNCTION) {
if (opa->filename && strcmp(opa->filename, new_filename) == 0) {
prefill_from_oparray(NULL, new_filename, opa TSRMLS_CC);
if (opa->reserved[XG(reserved_offset)] != 1/* && opa->filename && strcmp(opa->filename, new_filename) == 0)*/) {
prefill_from_oparray(opa->filename, opa TSRMLS_CC);
}
}

Expand All @@ -292,15 +289,20 @@ static int prefill_from_class_table(zend_class_entry *class_entry, int num_args,

new_filename = va_arg(args, char*);
if (ce->type == ZEND_USER_CLASS) {
zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) prefill_from_function_table, 1, new_filename);
if (!(ce->ce_flags & ZEND_XDEBUG_VISITED)) {
ce->ce_flags |= ZEND_XDEBUG_VISITED;
zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) prefill_from_function_table, 1, new_filename);
}
}

return ZEND_HASH_APPLY_KEEP;
}

void xdebug_prefill_code_coverage(function_stack_entry *fse, zend_op_array *op_array TSRMLS_DC)
void xdebug_prefill_code_coverage(zend_op_array *op_array TSRMLS_DC)
{
prefill_from_oparray(fse, op_array->filename, op_array TSRMLS_CC);
if (op_array->reserved[XG(reserved_offset)] == 0) {
prefill_from_oparray(op_array->filename, op_array TSRMLS_CC);
}

zend_hash_apply_with_arguments(CG(function_table), (apply_func_args_t) prefill_from_function_table, 1, op_array->filename);
zend_hash_apply_with_arguments(CG(class_table), (apply_func_args_t) prefill_from_class_table, 1, op_array->filename);
Expand Down
2 changes: 1 addition & 1 deletion xdebug_code_coverage.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void xdebug_coverage_line_dtor(void *data);
void xdebug_coverage_file_dtor(void *data);

void xdebug_count_line(char *file, int lineno, int executable, int deadcode TSRMLS_DC);
void xdebug_prefill_code_coverage(function_stack_entry *fse, zend_op_array *op_array TSRMLS_DC);
void xdebug_prefill_code_coverage(zend_op_array *op_array TSRMLS_DC);

PHP_FUNCTION(xdebug_start_code_coverage);
PHP_FUNCTION(xdebug_stop_code_coverage);
Expand Down
2 changes: 2 additions & 0 deletions xdebug_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ typedef struct xdebug_var {

#define XDEBUG_ERROR_ENCODING_NOT_SUPPORTED 900

#define ZEND_XDEBUG_VISITED 0x1000000

typedef struct _xdebug_func {
char *class;
char *function;
Expand Down

0 comments on commit 9e76e80

Please sign in to comment.