1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-11-04 08:17:17 -05:00

CSS bug 766: Scan ancestor elements only if needed.

time elinks -no-connect -no-home 'http://rss.slashdot.org/Slashdot/slashdot/to?m=5878'
Wait until finished loading, then press q and Enter.

before	6.45user 0.17system 0:11.34elapsed 58%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3387minor)pagefaults 0swaps
after	5.51user 0.14system 0:09.85elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3469minor)pagefaults 0swaps
before	5.86user 0.17system 0:10.58elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3504minor)pagefaults 0swaps
after	5.50user 0.15system 0:10.96elapsed 51%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3645minor)pagefaults 0swaps
before	6.40user 0.14system 0:11.85elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3640minor)pagefaults 0swaps
after	6.17user 0.12system 0:10.80elapsed 58%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3378minor)pagefaults 0swaps
before	5.80user 0.14system 0:10.29elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3632minor)pagefaults 0swaps
after	5.56user 0.16system 0:10.08elapsed 56%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3569minor)pagefaults 0swaps
before	5.92user 0.14system 0:10.54elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3570minor)pagefaults 0swaps
after	5.52user 0.13system 0:10.10elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k
	0inputs+0outputs (0major+3515minor)pagefaults 0swaps

All in all, it is doubtful whether this change is worth the complexity.
Please go ahead and revert if you think it isn't.
This commit is contained in:
Kalle Olavi Niemitalo 2007-07-15 21:53:35 +03:00 committed by Kalle Olavi Niemitalo
parent ace03d5093
commit 591ff81890
4 changed files with 66 additions and 30 deletions

View File

@ -141,7 +141,8 @@ examine_element(struct html_context *html_context, struct css_selector *base,
dbginfo(sel, type, base); \
merge_css_selectors(base, sel); \
/* Ancestor matches? */ \
if ((struct list_head *) element->next \
if (sel->leaves.may_contain_rel_ancestor \
&& (struct list_head *) element->next \
!= &html_context->stack) { \
struct html_element *ancestor; \
/* This is less effective than doing reverse iterations,
@ -227,7 +228,7 @@ get_css_selector_for_element(struct html_context *html_context,
assert(element && element->options && css);
selector = init_css_selector(NULL, CST_ELEMENT, NULL, 0);
selector = init_css_selector(NULL, CST_ELEMENT, CSR_ROOT, NULL, 0);
if (!selector)
return NULL;
@ -247,7 +248,7 @@ get_css_selector_for_element(struct html_context *html_context,
struct css_selector *stylesel;
struct scanner scanner;
stylesel = init_css_selector(NULL, CST_ELEMENT, NULL, 0);
stylesel = init_css_selector(NULL, CST_ELEMENT, CSR_ROOT, NULL, 0);
if (stylesel) {
init_scanner(&scanner, &css_scanner_info, code, NULL);

View File

@ -386,7 +386,7 @@ css_parse_selector(struct css_stylesheet *css, struct scanner *scanner,
* wasn't marked so and thus wasn't bound to
* the stylesheet. Let's do that now. */
assert(prev_element_selector);
prev_element_selector->relation = CSR_ROOT;
set_css_selector_relation(prev_element_selector, CSR_ROOT);
prev_element_selector =
reparent_selector(&css->selectors,
prev_element_selector,
@ -404,11 +404,11 @@ css_parse_selector(struct css_stylesheet *css, struct scanner *scanner,
if (!selector) continue;
assert(prev_element_selector);
set_css_selector_relation(prev_element_selector, reltype);
add_css_selector_to_set(prev_element_selector,
&selector->leaves);
last_chained_selector = prev_element_selector;
prev_element_selector->relation = reltype;
}

View File

@ -45,7 +45,9 @@ find_css_selector(struct css_selector_set *sels, enum css_selector_type type,
}
struct css_selector *
init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
init_css_selector(struct css_selector_set *sels,
enum css_selector_type type,
enum css_selector_relation relation,
unsigned char *name, int namelen)
{
struct css_selector *selector;
@ -53,7 +55,7 @@ init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
selector = mem_calloc(1, sizeof(*selector));
if (!selector) return NULL;
selector->relation = CSR_ROOT; /* Default */
selector->relation = relation;
init_css_selector_set(&selector->leaves);
selector->type = type;
@ -78,6 +80,17 @@ init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
return selector;
}
void
set_css_selector_relation(struct css_selector *selector,
enum css_selector_relation relation)
{
/* Changing the relation after the selector is in a set might
* require setting css_relation_set.may_contain_rel_ancestor,
* but we don't have a pointer to the set here. */
assert(!css_selector_is_in_set(selector));
selector->relation = relation;
}
struct css_selector *
get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
enum css_selector_relation rel,
@ -91,13 +104,7 @@ get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
return selector;
}
selector = init_css_selector(sels, type, name, namelen);
if (selector) {
selector->relation = rel;
return selector;
}
return NULL;
return init_css_selector(sels, type, rel, name, namelen);
}
static struct css_selector *
@ -106,8 +113,9 @@ copy_css_selector(struct css_stylesheet *css, struct css_selector *orig)
struct css_selector *copy;
assert(css && orig);
assert(orig->relation == CSR_ROOT);
copy = init_css_selector(&css->selectors, orig->type,
copy = init_css_selector(&css->selectors, orig->type, CSR_ROOT,
orig->name, strlen(orig->name));
if (!copy)
return NULL;
@ -183,6 +191,13 @@ done_css_selector(struct css_selector *selector)
mem_free(selector);
}
void
init_css_selector_set(struct css_selector_set *set)
{
set->may_contain_rel_ancestor = 0;
init_list(set->list);
}
void
done_css_selector_set(struct css_selector_set *set)
{
@ -191,6 +206,25 @@ done_css_selector_set(struct css_selector_set *set)
}
}
void
add_css_selector_to_set(struct css_selector *selector,
struct css_selector_set *set)
{
assert(!css_selector_is_in_set(selector));
add_to_list(set->list, selector);
if (selector->relation == CSR_ANCESTOR)
set->may_contain_rel_ancestor = 1;
}
void
del_css_selector_from_set(struct css_selector *selector)
{
del_from_list(selector);
selector->next = NULL;
selector->prev = NULL;
}
#ifdef DEBUG_CSS
void
dump_css_selector_tree_iter(struct css_selector_set *sels, int level)

View File

@ -41,19 +41,14 @@
* because all rules for the same selector have already been merged
* into one struct css_selector. */
struct css_selector_set {
#ifdef CONFIG_DEBUG
/* Cause a crash if struct css_selector_set * is cast to
* struct list_head *. */
char dummy;
#endif
unsigned char may_contain_rel_ancestor;
/* Keep this away from the beginning of the structure,
* so that nobody can cast the struct css_selector_set *
* to struct list_head * and get away with it. */
struct list_head list; /* -> struct css_selector */
};
#ifdef CONFIG_DEBUG
# define INIT_CSS_SELECTOR_SET(set) { 0, { D_LIST_HEAD(set.list) } }
#else
# define INIT_CSS_SELECTOR_SET(set) { { D_LIST_HEAD(set.list) } }
#endif
#define INIT_CSS_SELECTOR_SET(set) { 0, { D_LIST_HEAD(set.list) } }
/* The {struct css_selector} is used for mapping elements (or nodes) in the
* document structure to properties. See README for some hints about how the
@ -65,7 +60,8 @@ struct css_selector {
LIST_HEAD(struct css_selector);
/* This defines relation between this selector fragment and its
* parent in the selector tree. */
* parent in the selector tree.
* Update with set_css_selector_relation(). */
enum css_selector_relation {
CSR_ROOT, /* First class stylesheet member. */
CSR_SPECIFITY, /* Narrowing-down, i.e. the "x" in "foo#x". */
@ -152,6 +148,7 @@ struct css_selector *find_css_selector(struct css_selector_set *set,
* your POV. */
struct css_selector *init_css_selector(struct css_selector_set *set,
enum css_selector_type type,
enum css_selector_relation relation,
unsigned char *name, int namelen);
/* Add all properties from the list to the given @selector. */
@ -161,15 +158,19 @@ void add_selector_properties(struct css_selector *selector,
/* Join @sel2 to @sel1, @sel1 taking precedence in all conflicts. */
void merge_css_selectors(struct css_selector *sel1, struct css_selector *sel2);
/* Use this function instead of modifying css_selector.relation directly. */
void set_css_selector_relation(struct css_selector *,
enum css_selector_relation);
/* Destroy a selector. done_css_stylesheet() normally does that for you. */
void done_css_selector(struct css_selector *selector);
#define init_css_selector_set(set) init_list((set)->list)
void init_css_selector_set(struct css_selector_set *set);
void done_css_selector_set(struct css_selector_set *set);
#define css_selector_set_empty(set) list_empty((set)->list)
#define css_selector_set_front(set) ((struct css_selector *) ((set)->list.next))
#define del_css_selector_from_set(selector) del_from_list(selector)
#define add_css_selector_to_set(selector, set) add_to_list((set)->list, (selector))
void add_css_selector_to_set(struct css_selector *, struct css_selector_set *);
void del_css_selector_from_set(struct css_selector *);
#define css_selector_is_in_set(selector) ((selector)->next != NULL)
#define foreach_css_selector(selector, set) foreach (selector, (set)->list)