Skip to content

Commit

Permalink
- Improve code coverage gathering performace by 1000%.
Browse files Browse the repository at this point in the history
SVN Rev: 2533
  • Loading branch information
derickr committed Oct 11, 2007
1 parent 9f4bdec commit 71167cf
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
Expand Up @@ -158,8 +158,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;

/* superglobals */
zend_bool dump_globals;
Expand Down
15 changes: 11 additions & 4 deletions xdebug.c
Expand Up @@ -537,6 +537,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 @@ -564,6 +566,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 @@ -713,7 +718,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 @@ -840,7 +844,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 @@ -1483,7 +1486,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 @@ -2336,7 +2339,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
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
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
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 71167cf

Please sign in to comment.