# Memory documentation of the layout module

Copyright © 1995-2006 Opera Software AS. All rights reserved. This file is part of the Opera web browser. It may not be distributed under any circumstances.

## OOM policies

When memory allocation fails, the layout module will signal and check this in the following ways:

### LEAVE

Except in module initialization (the LayoutModule class), LEAVE is not used.

### Return values from methods

OpStatus / OpBoolean
  Widely used, especially in the cascade code.
LAYST
  LAYST is a status type defined and used by the layout module. It may be used to indicate OOM conditions, in which case its value is LAYOUT_OUT_OF_MEMORY
FALSE
  The value FALSE of type BOOL
NULL-pointer
  Sometimes a NULL-pointer is returned to indicate OOM

### Flags

HLDocProfile
  The methods GetIsOutOfMemory() and SetIsOutOfMemory() of the HLDocProfile class in the logdoc module are both used in the layout module
TraversalObject
  The methods IsOutOfMemory() and SetOutOfMemory() of the TraversalObject class are used to signal OOM conditions

## Who is handling OOM?

The layout module itself does nothing else than notify the caller of it and perform necessary clean-up to avoid memory leaks, if something got incompletely initialized before the allocation failure occurred.

## Where and when is memory allocated

During initialization of Opera, LayoutModule allocates some memory, which is not freed before Opera shuts down. This is memory that is so frequently used by the layout engine that performance would suffer if not kept in memory at all times. There are a few memory pools for objects very frequently allocated and freed, most notably LayoutProperties, of which several are allocated temporarily during reflow and traversal. The number of total simultaneous objects of this type may be as high as the maximum depth of the HTML tree in the document to be reflowed or traversed. The total number of objects allocated during a reflow or traversal may be as high as the total number of elements in the document.

The memory allocated by LayoutModule is the only permanently allocated memory in the layout module. The remaining memory allocations in this module are triggered by document loading.

When building the layout tree (reflow), memory is allocated for each layout box (normally one box per HTML element) generated.

Memory is temporarily allocated and freed during reflow and traversal (LayoutProperties objects), but this memory will normally be taken from the memory pool in LayoutModule.

## Heap memory used

The amount of heap memory is proportional with the size of the document that is to be laid out. Each HTML block element will take xxx bytes in the layout module. Each text node will take xxx bytes. The layout module does not copy the actual text -- it is served by and shared with the logdoc module.

## Stack memory used

The layout module has very few stack-allocated arrays, but a couple exist. Both are relatively small (100 characters) and marked with "ARRAY OK".

The function call stack depth depends on the HTML tree depth. During traversal and reflow, the layout module will typically add two function calls to the stack when entering an HTML element.

## Static memory used

Whatever the LayoutModule object allocates should be counted as "static memory", since it is allocated (on the heap) when Opera starts up and freed when Opera exits. In addition there is one small constant array for Roman numbers.

## Caching

Most of the data allocated and kept by the layout module (typically Box and Content derived classes), can (almost) be considered to be a kind of a cache. Currently, form element content, plug-ins and applets are owned by the layout module (but they could probably be moved elsewhere), but apart from this, there is nothing in the layout module that cannot be regenerated from the data in the logdoc module.

The layout boxes (the Box and Content classes) are normally kept in memory as long as the owning HTML_Element is there. The layout boxes are mainly there to speed up traversal (by a lot -- this speed-up is really essential most of the time while displaying or interacting with the document). The box data is needed only when the tree is to be traversed, but generating the boxes (reflow) is not a fast operation. Each paint event, each mouse motion event, (and other events) will trigger a traversal.

## Clean-up before exiting

When all documents are freed from memory, all that is left of allocations in the layout module should be the ones done by the LayoutModule object. When Opera exits, the LayoutModule object is deleted, which will free the remaining memory kept by the layout module.

## Temporary buffers

The layout module uses the temporary buffer owned by MemoryManager very rarely. The only case where it used, is when setting and getting the text from OPTION elements. When getting the text, the temporary buffer is returned from the callee in the layout module to the caller in a different module. The temporary memory buffer is involved in a lot of operations here as well, and even if this is (hopefully) a safe thing to do today, this solution is very fragile.

## Memory usage tuning

There are no direct ways of tuning memory usage. However, some features, such as BiDi, requires additional memory, and can be disabled to reduce memory usage (and functionality).

## Memory usage checking

None

## How to get high coverage

Memory allocations are done from a relatively few sites in the layout module. The main sites are:

- The LayoutModule object
- When creating a layout box (Box + Content)
- When initializing reflow state object during reflow (each Box and Content object have their own object)
- When creating a new chain in the cascade (a LayoutProperties object) during reflow and traversal. Since LayoutProperties objects are allocated from a pool, actual memory allocation will normally not take place, unless we need more LayoutProperties than the pool can provide (deep HTML trees)
- When adding a line (of text and other inline elements) to a container (block)
- When laying out text nodes. There is a structure per layout box that contains various information about each word. For large text nodes, we may allocate quite big chunks of data here.
- SVG

Laying out any document containing text will cause memory to be allocated from all the above sites. There are however slightly different allocation sites for each Box / Content type.

In addition we have these sites:

- BiDi calculation
- BUTTON, SELECT, OPTION, OPTGROUP elements
- Elements with overflow:scroll
- Run-ins converted a block / inline
- Page breaking
- Java applets
- Tables
- Text search
- Link traversal
- WantToModifyProperties
- CURRENT_STYLE_SUPPORT

## Design choices

TODO

## Possible improvements

Reduce the size of an HTMLayoutProperties object
  The HTMLayoutProperties structure is large (it took 600 bytes on an x86 architecture when this documentation was written), and during layout and traversal several simultaneous instances are created, and accessed extensively. On devices with low memory performance, this may be a problem.
Avoid potentially dangerous usage of the MemoryManager temporary buffers
  If the layout module needs temporary buffers frequently, a temporary buffer owned and used by the layout module should be created, instead of using the global MemoryManager temporary buffer
Delete layout boxes when not needed for a while
  If it is unlikely that the layout boxes are to be traversed for a while, we could consider deleting them (rebuilding them is expensive). However, currently, some layout boxes keep data which it is not possible to regenerate if deleted, so we need to solve those issues first.

## MAP compliance

not so far