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.
 
 
 
 
 
 

516 lines
23 KiB

<h1 id="compiling">Compiling</h1>
<h2>Automatic defaults</h2>
<p>If you compile Duktape with no compiler options, Duktape will detect the
compiler and the platform automatically and select defaults appropriate in
most cases. Recommended compiler options (for GCC/clang, use similar options
in your compiler):</p>
<ul>
<li><code>-std=c99</code>: recommended to ensure C99 semantics
which improve C type detection and allows Duktape to use variadic
macros (without these you may get harmless compiler warnings because
of the way Duktape works around the lack of variadic macros)</li>
<li><code>-Os</code>: optimize for smallest footprint, which is usually
desired when embedding Duktape</li>
<li><code>-fomit-frame-pointer</code>: omit frame pointer, further reduces
footprint but may interfere with debugging (leave out from debug builds)</li>
<li><code>-fstrict-aliasing</code>: use strict aliasing rules, Duktape
is compatible with these and they improve the resulting C code</li>
</ul>
<p>Duktape feature defaults are, at a high level:</p>
<ul>
<li>Full Ecmascript compliance
(including the optional
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-B">Annex B</a>
features), except for intentional real world compatibility deviations
(see <a href="#custombehavior">Custom behavior</a>)</li>
<li>Packed value representation (8 bytes per value) when available,
unpacked value representation (12-16 bytes per value) when not</li>
<li>Reference counting and mark-and-sweep garbage collection</li>
<li>Full error messages and tracebacks</li>
<li>No debug printing, no asserts, etc</li>
</ul>
<p>Usually the automatic defaults are OK. If you're using Duktape on a platform
where Duktape's automatic feature detection doesn't (yet) work, you may need to
force a specific byte order or alignment requirements with <b>feature options</b>
described below.</p>
<h2>Feature options (DUK_OPT_xxx)</h2>
<p>If you wish to modify the defaults, you can provide feature options in the
form of <code>DUK_OPT_xxx</code> compiler defines. These will be taken into
account by the internal <code>duk_features.h</code> file, which resolves the
final internal features based on feature requests, compiler features, and
platform features.</p>
<p>The available feature options can be found in <code>duk_features.h</code>.
The table below summarizes the available options, in no particular order:</p>
<table>
<thead>
<tr>
<th>Define</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="definename">DUK_OPT_NO_PACKED_TVAL</td>
<td>Don't use the packed 8-byte internal value representation even if otherwise
possible. The packed representation has more platform/compiler portability
issues than the unpacked one.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_FORCE_ALIGN</td>
<td>Use <code>-DDUK_OPT_FORCE_ALIGN=4</code> or <code>-DDUK_OPT_FORCE_ALIGN=8</code>
to force a specific struct/value alignment instead of relying on Duktape's
automatic detection. This shouldn't normally be needed.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_FORCE_BYTEORDER</td>
<td>Use this to skip byte order detection and force a specific byte order:
<code>1</code> for little endian, <code>2</code> for ARM "mixed" endian
(integers little endian, IEEE doubles mixed endian), <code>3</code> for
big endian. Byte order detection relies on unstandardized platform
specific header files, so this may be required for custom platforms if
compilation fails in endianness detection.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DEEP_C_STACK</td>
<td>By default Duktape imposes a sanity limit on the depth of the C stack
because it is often limited in embedded environments. This option
forces Duktape to use a deep C stack which relaxes e.g. recursion
limits. Automatic feature detection enables deep C stacks on some
platforms known to have them (e.g. Linux, BSD, Windows).</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_REFERENCE_COUNTING</td>
<td>Disable reference counting and use only mark-and-sweep for garbage collection.
Although this reduces memory footprint of heap objects, the downside is much
more fluctuation in memory usage.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_MARK_AND_SWEEP</td>
<td>Disable mark-and-sweep and use only reference counting for garbage collection.
This reduces code footprint and eliminates garbage collection pauses, but
objects participating in unreachable reference cycles won't be collected until
the Duktape heap is destroyed. In particular, function instances won't be
collected because they're always in a reference cycle with their default
prototype object. Unreachable objects are collected if you break reference
cycles manually (and are always freed when a heap is destroyed).</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_VOLUNTARY_GC</td>
<td>Disable voluntary periodic mark-and-sweep collection. A mark-and-sweep
collection is still triggered in an out-of-memory condition. This option
should usually be combined with reference counting, which collects all
non-cyclical garbage. Application code should also request an explicit
garbage collection from time to time when appropriate. When this option
is used, Duktape will have no garbage collection pauses in ordinary use,
which is useful for timing sensitive applications like games.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_MS_STRINGTABLE_RESIZE</td>
<td>Disable forced string intern table resize during mark-and-sweep garbage
collection. This may be useful when reference counting is disabled, as
mark-and-sweep collections will be more frequent and thus more expensive.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_GC_TORTURE</td>
<td>Development time option: force full mark-and-sweep on every allocation to
stress test memory management.</td>
</tr>
<td class="definename">DUK_OPT_NO_AUGMENT_ERRORS</td>
<td>Don't augment Ecmascript error objects with custom fields like
<code>fileName</code>, <code>lineNumber</code>, and traceback data.
Also disables <code>Duktape.errcreate</code> and <code>Duktape.errthrow</code>
error handler callbacks. Implies <code>DUK_OPT_NO_TRACEBACKS</code>.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_TRACEBACKS</td>
<td>Don't record traceback data into Ecmascript error objects (but still record
<code>fileName</code> and <code>lineNumber</code>). Reduces footprint and
makes error handling a bit faster, at the cost of less nformative Ecmascript
errors.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_VERBOSE_ERRORS</td>
<td>Don't provide error message strings or filename/line information for
errors generated by Duktape. Reduces footprint, at the cost of much
less informative Ecmascript errors.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_TRACEBACK_DEPTH</td>
<td>Override default traceback collection depth. The default is currently 10.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_PC2LINE</td>
<td>Don't record a "pc2line" map into function instances. Without this map,
exceptions won't have meaningful line numbers (virtual machine program
counter values cannot be translated to line numbers) but function instances
will have a smaller footprint.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_REGEXP_SUPPORT</td>
<td>Disable support for regular expressions. Regexp literals are treated as a
<code>SyntaxError</code>, RegExp constructor and prototype functions throw
an error, <code>String.prototype.replace()</code> throws an error if given
a regexp search value, <code>String.prototype.split()</code> throws an error
if given a regexp separator value, <code>String.prototype.search()</code>
and <code>String.prototype.match()</code> throw an error unconditionally.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_STRICT_UTF8_SOURCE</td>
<td>Enable strict UTF-8 parsing of source code. When enabled, non-shortest
encodings (normally invalid UTF-8) and surrogate pair codepoints are accepted
as valid source code characters. This option breaks compatibility with
some test262 tests.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_OCTAL_SUPPORT</td>
<td>Disable optional octal number support (Ecmascript E5/E5.1
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-B">Annex B</a>).</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_SOURCE_NONBMP</td>
<td>Disable accurate Unicode support for non-BMP characters in source code.
Non-BMP characters are then always accepted as identifier characters.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_BROWSER_LIKE</td>
<td>Disable browser-like functions. Makes <code>print()</code> and
<code>alert()</code> throw an error. This option is confusing when
used with the Duktape command line tool, as the command like tool
will immediately panic.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_SECTION_B</td>
<td>Disable optional features in Ecmascript specification
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-B">Annex B</a>.
Causes <code>escape()</code>, <code>unescape()</code>, and
<code>String.prototype.substr()</code> to throw an error.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_FUNC_STMT</td>
<td>Disable support for function declarations outside program or function top
level (also known as "function statements"). Such declarations are
non-standard and the strictly compliant behavior is to treat them as a
SyntaxError. Default behavior is to treat them like ordinary function
declarations ("hoist" them to function top) with V8-like semantics.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY</td>
<td>Add a non-standard <code>caller</code> property to non-strict function
instances for better compatibility with existing code. The semantics
of this property are not standardized and may vary between engines;
Duktape tries to behave close to V8 and Spidermonkey. See
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller">Mozilla</a>
description of the property. This feature disables tail call support.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY</td>
<td>Add a non-standard <code>source</code> property to function instances.
This allows function <code>toString()</code> to print out the actual
function source. The property is disabled by default because it increases
memory footprint.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT</td>
<td>For better compatibility with existing code, <code>Array.prototype.splice()</code>
has non-standard behavior by default when the second argument (deleteCount)
is not given: the splice operation is extended to the end of the array.
If this option is given, <code>splice()</code> will behave in a strictly
conforming fashion, treating a missing deleteCount the same as an undefined
(or 0) value.</td>
</tr>
<tr>
<td class="propname">DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY</td>
<td>Disable the non-standard (ES6 draft) <code>Object.prototype.__proto__</code>
property which is enabled by default.</td>
</tr>
<tr>
<td class="propname">DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF</td>
<td>Disable the non-standard (ES6 draft) <code>Object.setPrototypeOf</code>
method which is enabled by default.</td>
</tr>
<tr>
<td class="propname">DUK_OPT_NO_ES6_PROXY</td>
<td>Disable the non-standard (ES6 draft) <code>Proxy</code> object which
is enabled by default.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_JSONX</td>
<td>Disable support for the JSONX format. Reduces code footprint. Causes
JSONX calls to throw an error.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_JSONC</td>
<td>Disable support for the JSONC format. Reduces code footprint. Causes
JSONC calls to throw an error.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_FILE_IO</td>
<td>Disable use of ANSI C file I/O which might be a portability issue on some
platforms. Causes <code>duk_eval_file()</code> to throw an error,
makes built-in <code>print()</code> and <code>alert()</code> no-ops,
and suppresses writing of a panic message to <code>stderr</code> on panic.
This option does not suppress debug printing so don't enable debug printing
if you wish to avoid I/O.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_INTERRUPT_COUNTER</td>
<td>Disable the internal bytecode executor periodic interrupt counter.
The mechanism is used to implement e.g. execution step limit, custom
profiling, and debugger interaction. Disabling the interrupt counter
improves bytecode execution performance very slightly but disables all
features depending on it.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_NO_ZERO_BUFFER_DATA</td>
<td>By default Duktape zeroes data allocated for buffer values. Define
this to disable the zeroing (perhaps for performance reasons).</td>
</tr>
<tr>
<td class="definename">DUK_OPT_PANIC_HANDLER(code,msg)</td>
<td>Provide a custom panic handler, see detailed description below.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DECLARE</td>
<td>Provide declarations or additional #include directives to be used when
compiling Duktape. You may need this if you set <code>DUK_OPT_PANIC_HANDLER</code>
to call your own panic handler function (see example below). You can also
use this option to cause additional files to be included when compiling
Duktape.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_SEGFAULT_ON_PANIC</td>
<td>Cause the default panic handler to cause a segfault instead of using
<code>abort()</code> or <code>exit()</code>. This is useful when debugging
with valgrind, as a segfault provides a nice C traceback in valgrind.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_SELF_TESTS</td>
<td>Perform run-time self tests when a Duktape heap is created. Catches
platform/compiler problems which cannot be reliably detected during
compile time. Not enabled by default because of the extra footprint.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_ASSERTIONS</td>
<td>Enable internal assert checks. These slow down execution considerably
so only use when debugging.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DEBUG</td>
<td>Enable debug printouts.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DDEBUG</td>
<td>Enable more debug printouts.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DDDEBUG</td>
<td>Enable even more debug printouts. Not recommended unless you have
grep handy.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DPRINT_COLORS</td>
<td>Enable coloring of debug prints with
<a href="http://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape codes</a>.
The behavior is not sensitive to terminal settings.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DPRINT_RDTSC</td>
<td>Print RDTSC cycle count in debug prints if available.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_DEBUG_BUFSIZE</td>
<td>Debug code uses a static buffer as a formatting temporary to avoid side
effects in debug prints. The static buffer is large by default, which may
be an issue in constrained environments. You can set the buffer size
manually with this option. Example:
<code class="nobreak">-DDUK_OPT_DEBUG_BUFSIZE=2048</code>.</td>
</tr>
<tr>
<td class="definename">DUK_OPT_HAVE_CUSTOM_H</td>
<td>Enable user-provided <code>duk_custom.h</code> customization header
(see below for details). Not recommended unless really necessary.</td>
</tr>
</tbody>
</table>
<h2>Suggested feature options for some environments</h2>
<h3 id="timing-sensitive-options">Timing sensitive applications (e.g. games)</h3>
<ul>
<li>Use the default memory management settings (reference counting and
mark-and-sweep) but enable <code>DUK_OPT_NO_VOLUNTARY_GC</code> to
eliminate mark-and-sweep pauses. Use explicit GC calls (either
<code>duk_gc()</code> from C or <code>Duktape.gc()</code> from
Ecmascript) when possible to collect circular references.</li>
</ul>
<h3 id="memory-constrained-options">Memory constrained applications</h3>
<ul>
<li>Use the default memory management settings: although reference counting
increases heap header size, it also reduces memory usage fluctuation
which is often more important than absolute footprint.</li>
<li>Reduce error handling footprint with one or more of:
<code>DUK_OPT_NO_AUGMENT_ERRORS</code>,
<code>DUK_OPT_NO_TRACEBACKS</code>,
<code>DUK_OPT_NO_VERBOSE_ERRORS</code>,
<code>DUK_OPT_NO_PC2LINE</code>.</li>
<li>If you don't need the Duktape-specific additional JSONX/JSONC formats,
use both <code>DUK_OPT_NO_JSONX</code> and <code>DUK_OPT_NO_JSONC</code>.</li>
<li>If you don't need regexp support, use <code>DUK_OPT_NO_REGEXP_SUPPORT</code>.</li>
<li>Duktape debug code uses a large, static temporary buffer for formatting debug
log lines. Use e.g. <code class="nobreak">-DDUK_OPT_DEBUG_BUFSIZE=2048</code> to reduce
this overhead.</li>
</ul>
<h2>DUK_OPT_HAVE_CUSTOM_H and duk_custom.h</h2>
<p>Normally you define <code>DUK_OPT_xxx</code> feature options and the
internal <code>duk_features.h</code> header resolves these with platform/compiler
constraints to determine effective compilation options for Duktape internals.
The effective options are provided as <code>DUK_USE_xxx</code> defines which
you normally never see.</p>
<p>If you define <code>DUK_OPT_HAVE_CUSTOM_H</code>, Duktape will include
<code>duk_custom.h</code> after determining the appropriate <code>DUK_USE_xxx</code>
defines but before compiling any code. The <code>duk_custom.h</code> header,
which you provide, can then tweak the active <code>DUK_USE_xxx</code> defines
freely. See <code>duk_features.h</code> for the available defines.</p>
<p>This approach is useful when the <code>DUK_OPT_xxx</code> feature options
don't provide enough flexibility to tweak the build. The downside is that
you can easily create inconsistent <code>DUK_USE_xxx</code> flags, the
customization header will be version specific, and you need to peek into
Duktape internals to know what defines to tweak.</p>
<h2>DUK_OPT_PANIC_HANDLER</h2>
<p>The default panic handler will print an error message to stdout
unless I/O is disabled by <code>DUK_OPT_NO_FILE_IO</code>. It will then call
<code>abort()</code> or cause a segfault if
<code>DUK_OPT_SEGFAULT_ON_PANIC</code> is defined.</p>
<p>You can override the entire panic handler by defining
<code>DUK_OPT_PANIC_HANDLER</code>. For example, you could add the
following to your compiler options:</p>
<pre>
'-DDUK_OPT_PANIC_HANDLER(code,msg)={printf("*** %d:%s\n",(code),(msg));abort();}'
</pre>
<p>You can also use:</p>
<pre>
'-DDUK_OPT_PANIC_HANDLER(code,msg)={my_panic_handler((code),(msg))}'
</pre>
<p>which calls your custom handler:</p>
<pre class="c-code">
void my_panic_handler(int code, const char *msg) {
/* Your panic handling. Must not return. */
}
</pre>
<p>The <code>DUK_OPT_PANIC_HANDLER</code> macro is used internally by Duktape,
so your panic handler function needs to be declared for Duktape compilation to
avoid compiler warnings about undeclared functions. You can "inject" a declaration
for your function into Duktape compilation with:</p>
<pre>
'-DDUK_OPT_DECLARE=extern void my_panic_handler(int code, const char *msg);'
</pre>
<p>After this you might still get a compilation warning like "a noreturn function
must not return" as the compiler doesn't know your panic handler doesn't return.
You can fix this by either using a (compiler specific) "noreturn" declaration,
or by modifying the panic handler macro to something like:</p>
<pre>
'-DDUK_OPT_PANIC_HANDLER(code,msg)={my_panic_handler((code),(msg));abort()}'
</pre>
<p>As <code>abort()</code> is automatically a "noreturn" function the panic macro
body can no longer return. Duktape always includes <code>stdlib.h</code> which
provides the <code>abort()</code> prototype so no additional include files are
needed.</p>
<h2>Adding new feature options</h2>
<p>This section only applies if you customize Duktape internals and wish
to submit a patch to be included in the mainline distribution:</p>
<ul>
<li>Add a descriptive <code>DUK_OPT_xxx</code> for the custom feature.
The custom feature should only be enabled if the feature option is
explicitly given.</li>
<li>Modify <code>duk_features.h</code> to detect your custom feature
option and define appropriate internal <code>DUK_USE_xxx</code>
define(s). Conflicts with other features should be detected.
Code outside <code>duk_features.h</code> should only listen
to <code>DUK_USE_xxx</code> defines so that the resolution process
is fully contained in <code>duk_features.h</code>.</li>
</ul>
<h2>Memory management alternatives</h2>
<p>There are three supported memory management alternatives:</p>
<ul>
<li><b>Reference counting and mark-and-sweep (default)</b>: heap objects are
freed immediately when they become unreachable except for objects
participating in unreachable reference cycles. Such objects are freed by
a periodic voluntary, stop the world mark-and-sweep collection.
Mark-and-sweep is also used as the emergency garbage collector if
memory allocation fails.</li>
<li><b>Reference counting only</b>: reduces code footprint and eliminates
garbage collection pauses, but objects in unreachable reference cycles
are not collected until the Duktape heap is destroyed. This alternative
is not recommended unless the reference cycles are not an issue. See notes
below.</li>
<li><b>Mark-and-sweep only</b>: reduces code footprint and memory footprint
(heap headers don't need to store a reference count), but there is more
memory usage variance than in the default case. The frequency of voluntary,
stop the world mark-and-sweep collections is also higher than in the default
case where reference counting is expected to handle almost all memory
management.</li>
</ul>
<p>When using only reference counting it is important to avoid creating
unreachable reference cycles. Reference cycles are usually easy to avoid in
application code e.g. by using only forward pointers in data structures. Even
if reference cycles are necessary, garbage collection can be allowed to work
simply by breaking the cycles before deleting the final references to such objects.
For example, if you have a tree structure where nodes maintain references to
both children and parents (creating reference cycles for each node) you could
walk the tree and set the parent reference to <code>null</code> before deleting
the final reference to the tree.</p>
<p>Unfortunately every Ecmascript function instance is required to be in a
reference loop with an automatic prototype object created for the function.
You can break this loop manually if you wish. For internal technical reasons,
named function expressions are also in a reference loop; this loop cannot be
broken from user code and only mark-and-sweep can collect such functions.
See <a href="#limitations">Limitations</a>.</p>
<h2>Compiler warnings</h2>
<p>Current goal is for the Duktape compile to be clean when:</p>
<ul>
<li>using a major compiler (e.g. gcc, clang, MSVC, mingw);</li>
<li>the compiler is in C99 mode; and</li>
<li>warnings are enabled (e.g. <code>-Wall</code> in gcc/clang).</li>
</ul>
<p>There are still some warnings present when you compile with
<code>-Wextra</code> or equivalent option.</p>
<p>When your compiler is not C99 compliant, Duktape uses an awkward
replacement for variadic macros. This may cause, as a side effect, a
lot of harmless warnings if you set the compiler warning level too high.
This is difficult to fix, so C99 compilation may not be clean at the
moment.</p>