mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
5.1 KiB
135 lines
5.1 KiB
<h1 id="limitations">Limitations</h1>
|
|
|
|
<p>The following is a list of known limitations of the current implementation.
|
|
Limitations include shortcomings from a semantics perspective, performance
|
|
limitations, and implementation limits (which are inevitable).</p>
|
|
|
|
<p>Trivial bugs are not listed unless they are "long term bugs".</p>
|
|
|
|
<h2>No re-entrancy</h2>
|
|
|
|
<p>A single Duktape heap, i.e. contexts sharing the same garbage collector,
|
|
is <b>not re-entrant</b>. Only one C/C++ thread can call Duktape APIs
|
|
at a time for a particular Duktape heap (although the calling thread
|
|
can change over time).</p>
|
|
|
|
<h2>String and buffer limits</h2>
|
|
|
|
<p>The internal representation allows a maximum length of 2**31-1 (0x7fffffff)
|
|
<i>bytes</i> (not characters) for strings. 16-bit codepoints encode into 3
|
|
bytes of UTF-8 in the worst case, so the maximum string length which is
|
|
guaranteed to work is about 0.7G characters.</p>
|
|
|
|
<p>Buffer values are also limited to 2**31-1 (0x7fffffff) bytes.</p>
|
|
|
|
<h2>Property limits</h2>
|
|
|
|
<p>An object can have at most <code>DUK_HOBJECT_MAX_PROPERTIES</code> (an
|
|
internal define). Currently this limit is 0x7ffffffff.</p>
|
|
|
|
<h2>Regexp infinite loop</h2>
|
|
|
|
<p>The regexp engine gets stuck when a quantifier is used over an
|
|
empty match. For instance, the following should produce a "no match"
|
|
result but hits an internal recursion limit instead:</p>
|
|
|
|
<pre>
|
|
$ duk
|
|
duk> t = /(x*)*/.exec('y');
|
|
Error: Error: regexp executor recursion limit reached (rc=1) [ignored]
|
|
</pre>
|
|
|
|
<h2>Regexp dollar escape</h2>
|
|
|
|
<p>The Duktape RegExp syntax allows dollar escaping (e.g. <code>/\$/</code>)
|
|
even though it is not allowed by the E5.1 specification. RegExp dollar
|
|
escapes are used in existing Ecmascript code quite widely.</p>
|
|
|
|
<h2>Invalid stack indices</h2>
|
|
|
|
<p>The internal implementation for some stack operations (like
|
|
<code>duk_set_top()</code> uses pointer arithmetic. On 32-bit platforms
|
|
the pointer arithmetic may wrap and work in unexpected ways if stack
|
|
index values are large enough (e.g. 0x20000000 on a 32-bit platform
|
|
with 8-byte packed value type).</p>
|
|
|
|
<h2>Error handler model incomplete</h2>
|
|
|
|
<p>The model for error handlers is incomplete. Use <code>DUK_INVALID_INDEX</code>
|
|
as the error handler index for now.</p>
|
|
|
|
<h2>Unicode case conversion is not locale or context sensitive</h2>
|
|
|
|
<p>E5 Sections 15.5.4.16 to 15.5.4.19 require context and locale processing
|
|
of Unicode SpecialCasing.txt. However, we don't currently have a notion
|
|
of "current locale".</p>
|
|
|
|
<h2>Array performance when using non-default property attributes</h2>
|
|
|
|
<p>All array elements are expected to be writable, enumerable, and configurable
|
|
(default property attributes for new properties). If this assumption is violated,
|
|
even temporarily, the entire "array part" of an object is abandoned permanently
|
|
and array entries are moved to the "entry part". This involves interning all used
|
|
array indices as explicit string keys (e.g. "0", "1", etc). This is not a
|
|
compliance concern, but degrades performance.</p>
|
|
|
|
<h2>Compiler performance for inner functions</h2>
|
|
|
|
<p>Compiler needs multiple passes over the same function. Inner functions
|
|
are scanned <code>2**n</code> times, where <code>n</code> is the function level
|
|
(0, 1, ...).</p>
|
|
|
|
<h2>Global/eval code is slower than function code</h2>
|
|
|
|
<p>Bytecode generated for global and eval code cannot assign variables
|
|
statically to registers, and will use explicit name-based variable
|
|
read/write accesses. Bytecode generated for function code doesn't
|
|
have this limitation; most variables are assigned statically to registers
|
|
and direct register references are used used to access them.</p>
|
|
|
|
<p>This is a minor issue unless you spend a lot of time running top-level
|
|
global/eval code. The workaround is simple: put code in a function which
|
|
you call from the top level; for instance:</p>
|
|
<pre class="ecmascript-code">
|
|
function main() {
|
|
// ...
|
|
}
|
|
main();
|
|
</pre>
|
|
|
|
<p>There is also a common idiom of using an anonymous function for this
|
|
purpose:</p>
|
|
<pre class="ecmascript-code">
|
|
(function () {
|
|
// ...
|
|
})();
|
|
</pre>
|
|
|
|
<h2>Function temporaries may be live for garbage collection longer than expected</h2>
|
|
|
|
<p>Ecmascript functions are compiled into bytecode with a fixed set of
|
|
registers. Some registers are reserved for arguments and variable
|
|
bindings while others are used as temporaries. All registers are
|
|
considered live from a garbage collection perspective, even temporary
|
|
registers containing old values which the function actually cannot
|
|
reference any more. Such temporaries are considered reachable until they
|
|
are overwritten by the evaluation of another expression or until the
|
|
function exits. Function exit is the only easily predicted condition to
|
|
ensure garbage collection.</p>
|
|
|
|
<p>If you have a function which remains running for a very long time, it
|
|
should contain the bare minimum of variables and temporaries that could
|
|
remain live. For instance, you can structure code like:</p>
|
|
<pre class="ecmascript-code">
|
|
function runOnce() {
|
|
// run one iteration, lots of temporaries
|
|
}
|
|
|
|
function foreverLoop() {
|
|
for (;;) {
|
|
runOnce();
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>This is typically not an issue if there are no long-running functions.</p>
|
|
|