Skip to content
Permalink
Browse files

- MF20: Improve code coverage gathering performace by 1000%.

SVN Rev: 2535
  • Loading branch information
derickr committed Oct 11, 2007
1 parent b22ffad commit 9e76e8080423649bf1ad6d4837592d1336250e0b
Showing with 30 additions and 19 deletions.
  1. +1 −1 php_xdebug.h
  2. +11 −4 xdebug.c
  3. +15 −13 xdebug_code_coverage.c
  4. +1 −1 xdebug_code_coverage.h
  5. +2 −0 xdebug_private.h
@@ -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;
@@ -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
@@ -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);
@@ -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;
@@ -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);
@@ -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
@@ -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;
}
/* }}} */
@@ -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 &&
@@ -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
@@ -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) {
@@ -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);
}
}

@@ -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);
@@ -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);
@@ -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;

0 comments on commit 9e76e80

Please sign in to comment.
You can’t perform that action at this time.