From 074079fb5e1520106397d036a66d84c25d3486df Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sun, 15 Feb 2009 13:30:03 +0000 Subject: Most of the interned string lifetimes are at least no shorter than we think they ought to be. svn path=/trunk/libcss/; revision=6532 --- src/parse/parse.c | 42 ++++++++++++++++++++++++++++++++++----- src/parse/properties.c | 53 ++++++++++++++++++++++++++++++++++++++++++-------- src/stylesheet.c | 47 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 123 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/parse/parse.c b/src/parse/parse.c index 484be31..f195c50 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -145,6 +145,8 @@ static inline css_error parseMalformedDeclaration(css_parser *parser); static inline css_error parseMalformedSelector(css_parser *parser); static inline css_error parseMalformedAtRule(css_parser *parser); +static inline void unref_interned_strings_in_tokens(css_parser *parser); + /** * Dispatch table for parsing, indexed by major state number */ @@ -612,7 +614,8 @@ css_error getToken(css_parser *parser, const css_token **token) t->data.len, &t->idata); if (t->ilower == NULL) - t->ilower = t->idata; + t->ilower = lwc_context_string_ref(parser->dictionary, + t->idata); if (lerror != lwc_error_ok) return css_error_from_lwc_error(lerror); @@ -647,7 +650,7 @@ css_error pushBack(css_parser *parser, const css_token *token) /* The pushback buffer depth is 1 token. Assert this. */ assert(parser->pushback == NULL); - + perror = parserutils_vector_remove_last(parser->tokens); if (perror != PARSERUTILS_OK) return css_error_from_parserutils_error(perror); @@ -731,7 +734,8 @@ css_error parseStart(css_parser *parser) parser->event(CSS_PARSER_END_STYLESHEET, NULL, parser->event_pw); } - + + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); @@ -763,6 +767,7 @@ css_error parseStylesheet(css_parser *parser) if (error != CSS_OK) return error; + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); @@ -832,6 +837,7 @@ css_error parseRuleset(css_parser *parser) switch (state->substate) { case Initial: + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); error = getToken(parser, &token); @@ -1004,6 +1010,7 @@ css_error parseAtRule(css_parser *parser) switch (state->substate) { case Initial: + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); error = getToken(parser, &token); @@ -1158,14 +1165,15 @@ css_error parseBlock(css_parser *parser) parser->event_pw); } - parserutils_vector_clear(parser->tokens); - if (token->type != CSS_TOKEN_CHAR || lwc_string_length(token->ilower) != 1 || lwc_string_data(token->ilower)[0] != '{') { /* This should never happen, as FIRST(block) == '{' */ assert(0 && "Expected {"); } + unref_interned_strings_in_tokens(parser); + parserutils_vector_clear(parser->tokens); + state->substate = WS; /* Fall through */ case WS: @@ -1214,6 +1222,7 @@ css_error parseBlock(css_parser *parser) parser->event(CSS_PARSER_END_BLOCK, NULL, parser->event_pw); } + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); @@ -1345,6 +1354,7 @@ css_error parseSelector(css_parser *parser) parser_state to = { sAny1, Initial }; parser_state subsequent = { sSelector, AfterAny1 }; + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return transition(parser, to, subsequent); @@ -1371,6 +1381,7 @@ css_error parseDeclaration(css_parser *parser) parser_state to = { sProperty, Initial }; parser_state subsequent = { sDeclaration, Colon }; + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return transition(parser, to, subsequent); @@ -2040,6 +2051,7 @@ css_error parseMalformedDeclaration(css_parser *parser) return error; /* Discard the tokens we've read */ + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); @@ -2134,6 +2146,7 @@ css_error parseMalformedSelector(css_parser *parser) return error; /* Discard the tokens we've read */ + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); @@ -2241,12 +2254,31 @@ css_error parseMalformedAtRule(css_parser *parser) return error; /* Discard the tokens we've read */ + unref_interned_strings_in_tokens(parser); parserutils_vector_clear(parser->tokens); return done(parser); } +/** + * Iterate the token vector and unref any interned strings in the tokens. + * + * \param parser The parser whose tokens we are cleaning up. + */ +static inline void unref_interned_strings_in_tokens(css_parser *parser) +{ + int32_t ctx = 0; + const css_token *tok; + + while ((tok = parserutils_vector_iterate(parser->tokens, &ctx)) != NULL) { + if (tok->idata != NULL) + lwc_context_string_unref(parser->dictionary, tok->idata); + if (tok->ilower != NULL) + lwc_context_string_unref(parser->dictionary, tok->ilower); + } +} + #ifndef NDEBUG #ifdef DEBUG_STACK static void printer(void *item) diff --git a/src/parse/properties.c b/src/parse/properties.c index a4de6ef..f54b3f9 100644 --- a/src/parse/properties.c +++ b/src/parse/properties.c @@ -764,6 +764,7 @@ css_error parse_background_image(css_language *c, /* Copy the bytecode to it */ memcpy((*result)->bytecode, &opv, sizeof(opv)); if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_IMAGE_URI) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), &token->idata, sizeof(lwc_string *)); @@ -1760,8 +1761,11 @@ css_error parse_counter_increment(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } + + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(ptr, &name, sizeof(name)); ptr += sizeof(name); + memcpy(ptr, &increment, sizeof(increment)); ptr += sizeof(increment); @@ -1925,8 +1929,11 @@ css_error parse_counter_reset(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } + + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(ptr, &name, sizeof(name)); ptr += sizeof(name); + memcpy(ptr, &increment, sizeof(increment)); ptr += sizeof(increment); @@ -2001,6 +2008,7 @@ css_error parse_cue_after(css_language *c, /* Copy the bytecode to it */ memcpy((*result)->bytecode, &opv, sizeof(opv)); if ((flags & FLAG_INHERIT) == false && value == CUE_AFTER_URI) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), &token->idata, sizeof(lwc_string *)); @@ -2055,6 +2063,7 @@ css_error parse_cue_before(css_language *c, /* Copy the bytecode to it */ memcpy((*result)->bytecode, &opv, sizeof(opv)); if ((flags & FLAG_INHERIT) == false && value == CUE_BEFORE_URI) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), &token->idata, sizeof(lwc_string *)); @@ -2246,7 +2255,8 @@ css_error parse_cursor(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } - + + lwc_context_string_ref(c->sheet->dictionary, uri); memcpy(ptr, &uri, sizeof(uri)); ptr += sizeof(uri); @@ -2793,7 +2803,8 @@ css_error parse_font_family(css_language *c, while (token != NULL) { if (token->type == CSS_TOKEN_IDENT) { - lwc_string *name = token->idata; + lwc_string *tok_idata = token->idata; + lwc_string *name = tok_idata; lwc_string *newname; if (token->ilower == c->strings[SERIF]) { @@ -2903,6 +2914,12 @@ css_error parse_font_family(css_language *c, } if (opv == FONT_FAMILY_IDENT_LIST) { + /* Only ref 'name' again if the token owns it, + * otherwise we already own the only ref to the + * new name generated above. + */ + if (name == tok_idata) + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(ptr, &name, sizeof(name)); ptr += sizeof(name); } @@ -2913,7 +2930,8 @@ css_error parse_font_family(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } - + + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy(ptr, &token->idata, sizeof(token->idata)); ptr += sizeof(token->idata); @@ -3554,6 +3572,7 @@ css_error parse_list_style_image(css_language *c, /* Copy the bytecode to it */ memcpy((*result)->bytecode, &opv, sizeof(opv)); if ((flags & FLAG_INHERIT) == false && value == LIST_STYLE_IMAGE_URI) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), &token->idata, sizeof(lwc_string *)); @@ -4655,7 +4674,8 @@ css_error parse_play_during(css_language *c, memcpy((*result)->bytecode, &opv, sizeof(opv)); if ((flags & FLAG_INHERIT) == false && (value & PLAY_DURING_TYPE_MASK) == PLAY_DURING_URI) { - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), + lwc_context_string_ref(c->sheet->dictionary, uri); + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), &uri, sizeof(lwc_string *)); } @@ -4829,10 +4849,13 @@ css_error parse_quotes(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } - + + lwc_context_string_ref(c->sheet->dictionary, open); memcpy(ptr, &open, sizeof(open)); ptr += sizeof(open); - memcpy(ptr, &close, sizeof(close)); + + lwc_context_string_ref(c->sheet->dictionary, close); + memcpy(ptr, &close, sizeof(close)); ptr += sizeof(close); first = false; @@ -5964,7 +5987,8 @@ css_error parse_voice_family(css_language *c, while (token != NULL) { if (token->type == CSS_TOKEN_IDENT) { - lwc_string *name = token->idata; + lwc_string *tok_idata = token->idata; + lwc_string *name = tok_idata; lwc_string *newname; if (token->ilower == c->strings[MALE]) { @@ -6064,6 +6088,12 @@ css_error parse_voice_family(css_language *c, } if (opv == VOICE_FAMILY_IDENT_LIST) { + /* Only ref 'name' again if the token owns it, + * otherwise we already own the only ref to the + * new name generated above. + */ + if (name == tok_idata) + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(ptr, &name, sizeof(name)); ptr += sizeof(name); } @@ -6074,7 +6104,8 @@ css_error parse_voice_family(css_language *c, memcpy(ptr, &opv, sizeof(opv)); ptr += sizeof(opv); } - + + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy(ptr, &token->idata, sizeof(token->idata)); ptr += sizeof(token->idata); @@ -7296,6 +7327,7 @@ css_error parse_content_list(css_language *c, } if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy(buffer + offset, &token->idata, sizeof(token->idata)); } @@ -7314,6 +7346,7 @@ css_error parse_content_list(css_language *c, } if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy(buffer + offset, &token->idata, sizeof(token->idata)); } @@ -7340,6 +7373,7 @@ css_error parse_content_list(css_language *c, return CSS_INVALID; if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, token->idata); memcpy(buffer + offset, &token->idata, sizeof(token->idata)); } @@ -7419,6 +7453,7 @@ css_error parse_content_list(css_language *c, } if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(buffer + offset, &name, sizeof(name)); } @@ -7507,12 +7542,14 @@ css_error parse_content_list(css_language *c, } if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, name); memcpy(buffer + offset, &name, sizeof(name)); } offset += sizeof(name); if (buffer != NULL) { + lwc_context_string_ref(c->sheet->dictionary, sep); memcpy(buffer + offset, &sep, sizeof(sep)); } diff --git a/src/stylesheet.c b/src/stylesheet.c index e6dd5d9..41a3341 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -526,6 +526,8 @@ css_error css_stylesheet_style_create(css_stylesheet *sheet, uint32_t len, * \param sheet The stylesheet context * \param style The style to destroy * \return CSS_OK on success, appropriate error otherwise + * + * \todo This really ought to unref all the strings in the bytecode. */ css_error css_stylesheet_style_destroy(css_stylesheet *sheet, css_style *style) { @@ -562,7 +564,7 @@ css_error css_stylesheet_selector_create(css_stylesheet *sheet, memset(sel, 0, sizeof(css_selector)); sel->data.type = CSS_SELECTOR_ELEMENT; - sel->data.name = name; + sel->data.name = lwc_context_string_ref(sheet->dictionary, name); sel->data.value = NULL; /* Initial specificity -- 1 for an element, 0 for universal */ @@ -589,6 +591,7 @@ css_error css_stylesheet_selector_destroy(css_stylesheet *sheet, css_selector *selector) { css_selector *c, *d; + css_selector_detail *detail; if (sheet == NULL || selector == NULL) return CSS_BADPARM; @@ -600,9 +603,30 @@ css_error css_stylesheet_selector_destroy(css_stylesheet *sheet, for (c = selector->combinator; c != NULL; c = d) { d = c->combinator; + for (detail = &c->data; detail;) { + lwc_context_string_unref(sheet->dictionary, detail->name); + if (detail->value != NULL) + lwc_context_string_unref(sheet->dictionary, detail->value); + if (detail->next) + detail++; + else + detail = NULL; + } + sheet->alloc(c, 0, sheet->pw); } - + + for (detail = &selector->data; detail;) { + lwc_context_string_unref(sheet->dictionary, detail->name); + if (detail->value != NULL) + lwc_context_string_unref(sheet->dictionary, detail->value); + if (detail->next) + detail++; + else + detail = NULL; + } + + /* Destroy this selector */ sheet->alloc(selector, 0, sheet->pw); @@ -675,7 +699,12 @@ css_error css_stylesheet_selector_append_specific(css_stylesheet *sheet, (&temp->data)[num_details + 1] = *detail; /* Flag that there's another block */ (&temp->data)[num_details].next = 1; - + + /* Ref the strings */ + lwc_context_string_ref(sheet->dictionary, detail->name); + if (detail->value != NULL) + lwc_context_string_ref(sheet->dictionary, detail->value); + (*parent) = temp; /* Update parent's specificity */ @@ -839,11 +868,17 @@ css_error css_stylesheet_rule_destroy(css_stylesheet *sheet, css_rule *rule) } break; case CSS_RULE_CHARSET: + { + css_rule_charset *charset = (css_rule_charset *) rule; + lwc_context_string_unref(sheet->dictionary, charset->encoding); + } break; case CSS_RULE_IMPORT: { css_rule_import *import = (css_rule_import *) rule; - + + lwc_context_string_unref(sheet->dictionary, import->url); + if (import->sheet != NULL) css_stylesheet_destroy(import->sheet); } @@ -1015,7 +1050,7 @@ css_error css_stylesheet_rule_set_charset(css_stylesheet *sheet, assert(rule->type == CSS_RULE_CHARSET); /* Set rule's encoding field */ - r->encoding = charset; + r->encoding = lwc_context_string_ref(sheet->dictionary, charset); return CSS_OK; } @@ -1043,7 +1078,7 @@ css_error css_stylesheet_rule_set_nascent_import(css_stylesheet *sheet, assert(rule->type == CSS_RULE_IMPORT); /* Set the rule's sheet field */ - r->url = url; + r->url = lwc_context_string_ref(sheet->dictionary, url); r->media = media; return CSS_OK; -- cgit v1.2.3