Style Module Memory Documentation

Used OOM policies

The CSSManager interface methods leave when OOM occurs. SaveCSSWithInline(L) has two versions. One that leaves and one returning OP_STATUS. The CSS parser leaves, but is trapped before it reaches other modules through methods in the CSS class. RaiseCondition is never used within the style module.

Who is handling OOM?

An OOM situation during parsing of a style sheet needs to be handled by the module calling CSS::Load/LoadHtmlStyleAttr/LoadDOMStyleValue. The CSS object may represent a partially loaded style sheet, so the best thing is probably to delete the CSS object. The OOM failure is returned as an OP_STATUS and is handled by the logdoc and dom modules.

Description of flow

Loading style

The CSS class has three entry points for parsing style. Load is called from HTML_Element::LoadStyle (logdoc) for parsing full stylesheets, where the HTML_Element is a LINK or STYLE element referring to the style source. Imported stylesheets are loaded through dummy LINK elements.

LoadHtmlStyleAttr is used when parsing an html style attribute string (logdoc), and LoadDOMStyleValue is called from the dom module via SetProperty. The two latter produces a CSS_property_list object, while the former produces a CSS object.

CSSCollection

Only GetProperties and GetPageProperties are interesting when it comes to memory handling. They can fail if allocating new CSS_Elm objects for the selected properties fail. CSS_Elm are used as container elements for CSS_decl objects which are selected for a given html element during layout/display.

CSS Save

SaveCSSWithInline, which returns an OP_STATUS, is called from SaveHtmlWithInline (logdoc) as a part of saving a document locally.

Local stylesheets

Local stylesheets like user stylesheets, style for wml, mail, etc. Is loaded at startup and kept in memory until Opera exits. Some of them might be replaced by a reload during execution of Opera if preference settings change.

Heap memory usage

Heap memory usage is depending on the size of the stylesheets. The source code is stored in the HTML_Element as an ATTR_SRC_LIST, even after it is parsed and kept there until the element is deleted or changed via DOM. This is not really done in the style module, but still worth mentioning. The parsed style sheet is stored in various objects for representing selectors, rulesets, and declarations. All kept alive and referenced via CSS class objects. The CSS objects are kept alive by the document to which it belongs via HLDocProfile.

Additionally, the CSSManager contains CSS objects for the various loaded user stylesheets. They are loaded at startup and lives for the entire lifetime of the browser.

Stack memory usage

CSS_Ruleset::Match is called recursively. Max call depth depends on the number of simple selectors combined in a selector.

Bison parser

There is one recursive rule in the grammar which is not left-recursive. That is the rule for selector which is a combination of simple selectors. So a very long list of combined simple selectors will use a proportional amount of stack space:

DIV > DIV > DIV > DIV > DIV > DIV > ...

All other rules use left recursion, so the stack usage will be shallow. YYINITDEPTH defaults to 200, but could of course be set to something else if required.

Static memory usage

Caching and freeing memory

The parsed style information is stored with the document. If deleting the style information (CSS objects) without deleting the document is desired, deleting them is the responsibility of the document code (logdoc module).

Freeing memory on exit

The CSSManager object containing the local stylesheets is deleted in the Terminate function of initcore. All other non-static memory allocated via the style module is deleted with their respective document.

Temp buffers

Current use of MemoryManager temporary buffers

FormatCssValueL and FormatCssNumberL uses GetTempBuf2k() to format numbers, colors, and keywords.

Used a couple of places in the grammar in css_grammar.y to temporarily get the namespace URI and name for adding a namespace and retrieving the namespace idx.

GetMediaTypeString uses GetTempBuf() tempbuffer to return a media string from a media type bit set.

HTML_Element attributes are copied into GetTempBuf2() to get tokenized for matching attribute selectors.

Safety

FormatCssValueL and FormatCssNumberL use the tempbuffer to convert numbers to strings using system functions and they copy the result into a non-shared growable heap-buffer right away. So they won't be overwritten. I have not checked whether the code calling into this part of the style module (dom) is depending on temp buffers.

The attribute matching code is safe, because it is only using string comparison and tokenization calls on the tempbuffer before it's finished using the buffer.

GetMediaTypeString is not safe, because it is returned and used virtually everywhere. One interesting part is that GetMediaTypeString is used to retrieve the html element attribute value used for attribute selector matching. So in the case of matching the media attribute, the attribute is first generated into the GetTempBuf buffer and then copied into the GetTempBuf2 buffer to be tokenized.

Rewrite

The tempbuffer use in FormatCssValueL and FormatCssNumberL can easily be rewritten to use fixed size stack allocated strings, because the maximum size needed for converting a number to a string is relatively small and well known.

GetMediaTypeString is trickier because the string is returned upwards with all the other attribute strings which are not supposed to be freed by the caller.

Memory tuning

CSS_Buffer class uses less inlining when LIMITED_FOOTPRINT_DEVICE is defined.

Tests

None.

Coverage

Design choices

CSS_Buffer class was designed to use the buffers from the DataSrcElm objects to avoid duplicating the source. This has probably increased the footprint a bit to handle strings across buffer boundaries etc. Other design choices has been to minimize memory use by using limited-size bitfields for storing pseudo elements/classes, and integer types with low min/max values.

Suggestions of improvements

None.