Copyright © 1995-2005 Opera Software AS. All rights reserved.
This file is part of the Opera web browser. It may not be distributed
under any circumstances.
$Id$
All functions in the various classes in the module that comprise its
public API that can fail due to OOM signal such failures by
returning
OpStatus::ERR_NO_MEMORY.
In such case, the caller is responsible for handling the out of
memory condition.
When an out of memory condition occurs in a call directly from the
message loop (this includes, for instance, all out of memory
conditions signalled by the ECMAScript execution engine,) OOM is
signalled through a call to
Window::RaiseCondition
or
MemoryManager::RaiseCondition
(the latter if the ECMAScript environment is not one connected to a
document.)
When an asynchronous operation started through the
ES_AsyncInterface
interface fails due to OOM, this is (in addition to what is
described above) signalled by calling the registered callback with
the status
ES_ASYNC_NO_MEMORY.
In addition to propagating OOM signals to outside the module, out of memory conditions that occur while executing threads are also handled by killing all threads in the affected scheduler (thus returning it to its initial state.)
The code flow in the module is divided into two main cases:
ES_ThreadSchedulerImpl::AddRunnableES_ThreadSchedulerImpl::AddWaitingES_AsyncInterface::EvalES_LoadManager::RegisterScriptES_LoadManager::SetScriptES_LoadManager::WriteES_ThreadSchedulerImpl::HandleCallbackES_ThreadSchedulerImpl::RunNowES_Thread::EvaluateES_ThreadSchedulerImpl::HandleError)
and then propagated out of the module by 2.
Most memory allocated is used for control structures such as thread
schedulers
(ES_ThreadSchedulerImpl)
and threads
(ES_Thread
and subclasses) and for script generated document data (text
written by a script through a call to either of the functions
"document.write" and "document.writeln".) While both thread
schedulers and threads are fairly large objects, there are normally
few alive at any given time (at most one scheduler per document, and
zero or more threads per thread scheduler.) Threads are deallocated
as soon as they finish executing. The amount of script generated
document data depends entirely on scripts on the page. There is no
upper limit. Script generated document data is allocated in blocks
of fixed size (see "Memory tuning") and freed (blockwise) as soon as
it has been consumed by the document (HTML or XML) parser.
Some threads own potentially large heap allocated structures from
the ECMAScript module, represented by
ES_Context
and
ES_Program
objects. Such objects are freed by the threads when the threads are
deallocated. Most memory referenced by such objects are probably
owned and freed by the ECMAScript garbage collector at an unknown
time after the objects have been freed.
The module uses insignificant amounts of stack memory. There are no complex recursive functions or stack allocated arrays larger than a few bytes.
The module has no caching, and there is no non-destructive way to free memory. It is possible to kill all currently alive threads and thus free them and memory referenced from them by calling the function ES_ThreadScheduler::RemoveThreads.
Freeing memory on exit is dependant on that someone else frees all
ES_ThreadScheduler
and
ES_Environment
objects. This is typically the responsibility of the DOM module (in
the case of thread schedulers) and whatever code that created the
ES_Environment
object (currently only Voice XML code does that.)
The module uses the shared buffer returned by the function
MemoryManager::GetTempBuf.
In one case it is simply to avoid having to allocate a separate
string (pure optimization that is easy to remove) and in all other
cases the shared buffer is used to return a generated string from a
function without making the caller (which is in the ECMAScript
module) responsible for deallocating the returned string. Changing
this requires either using a non-shared but still globally allocated
buffer, or to rewrite the function and the code that calls it so
that the caller deallocates the string.
The class load manager (ES_LoadManager) uses a list of blocks to store script generated data. The size of the blocks in that list depends on the tweak TWEAK_ESUTILS_BLOCK_DATA_SIZE. No other memory tuning is possible.
There are no tests specificly for testing memory usage.
Running the "Scheduler regression tests" in the jstest2 CVS module and the selftests in the ECMAScript Utils module ("ESUtils.*") should provide good coverage for the code that is likely to be handling out of memory conditions.
There are no design choices in the module's design relating directly to balancing memory usage, footprint, performance and/or design. Or put differently: essentially no compromises between the different priorities have been made.
There are currently no planned improvements with regards to memory handling.