Files
wren/embedding/configuring-the-vm.html
Bob Nystrom 5cac3af2f2 Fresh docs!
2017-10-19 07:05:45 -07:00

235 lines
14 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Configuring the VM &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top" class="embedding">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<section>
<h2>embedding</h2>
<ul>
<li><a href="./">Introduction</a></li>
<li><a href="slots-and-handles.html">Slots and Handles</a></li>
<li><a href="calling-wren-from-c.html">Calling Wren from C</a></li>
<li><a href="calling-c-from-wren.html">Calling C from Wren</a></li>
<li><a href="storing-c-data.html">Storing C Data</a></li>
<li><a href="configuring-the-vm.html">Configuring the VM</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<td><h2>embedding</h2></td>
<td><h2>?</h2></td>
<td><h2>?</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="./">Introduction</a></li>
<li><a href="slots-and-handles.html">Slots and Handles</a></li>
<li><a href="calling-wren-from-c.html">Calling Wren from C</a></li>
<li><a href="calling-c-from-wren.html">Calling C from Wren</a></li>
<li><a href="storing-c-data.html">Storing C Data</a></li>
<li><a href="configuring-the-vm.html">Configuring the VM</a></li>
</ul>
</td>
<td>
<ul>
</ul>
</td>
<td>
<ul>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h1>Configuring the VM</h1>
<p>When you create a Wren VM, you tweak it by passing in a pointer to a
WrenConfiguration structure. Since Wren has no global state, you can configure
each VM differently if your application happens to run multiple. </p>
<p>The struct looks like: </p>
<div class="codehilite"><pre><span></span><span class="k">typedef</span> <span class="k">struct</span>
<span class="p">{</span>
<span class="n">WrenReallocateFn</span> <span class="n">reallocateFn</span><span class="p">;</span>
<span class="n">WrenLoadModuleFn</span> <span class="n">loadModuleFn</span><span class="p">;</span>
<span class="n">WrenBindForeignMethodFn</span> <span class="n">bindForeignMethodFn</span><span class="p">;</span>
<span class="n">WrenBindForeignClassFn</span> <span class="n">bindForeignClassFn</span><span class="p">;</span>
<span class="n">WrenWriteFn</span> <span class="n">writeFn</span><span class="p">;</span>
<span class="n">WrenErrorFn</span> <span class="n">errorFn</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">initialHeapSize</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">minHeapSize</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">heapGrowthPercent</span><span class="p">;</span>
<span class="p">}</span> <span class="n">WrenConfiguration</span><span class="p">;</span>
</pre></div>
<p>Most fields have useful defaults, which you can (and should) initialize by
calling: </p>
<div class="codehilite"><pre><span></span><span class="n">wrenInitConfiguration</span><span class="p">(</span><span class="o">&amp;</span><span class="n">configuration</span><span class="p">);</span>
</pre></div>
<p>Calling this ensures that your VM doesn&rsquo;t get uninitialized configuration when
new fields are added to WrenConfiguration. Here is what each field does, roughly
categorized: </p>
<h2>Binding <a href="#binding" name="binding" class="header-anchor">#</a></h2>
<p>The VM is isolated from the outside world. These callbacks let the VM request
access to imported code and foreign functionality. </p>
<h3><code>loadModuleFn</code> <a href="#loadmodulefn" name="loadmodulefn" class="header-anchor">#</a></h3>
<p>This is the callback Wren uses to load an imported module. The VM itself does
not know how to talk to the file system, so when an <code>import</code> statement is
executed, it relies on the host application to locate and read the source code
for a module. </p>
<p>The signature of this function is: </p>
<div class="codehilite"><pre><span></span><span class="kt">char</span><span class="o">*</span> <span class="n">loadModule</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">)</span>
</pre></div>
<p>When a module is imported, Wren calls this and passes in the module&rsquo;s name. The
host should return the source code for that module. Memory for the source should
be allocated using the same allocator that the VM uses for other allocation (see
below). Wren will take ownership of the returned string and free it later. </p>
<p>The module loader is only be called once for any given module name. Wren caches
the result internally so subsequent imports of the same module use the
previously loaded code. </p>
<p>If your host application isn&rsquo;t able to load a module with some name, it should
return <code>NULL</code> and Wren will report that as a runtime error. </p>
<p>If you don&rsquo;t use any <code>import</code> statements, you can leave this <code>NULL</code>. </p>
<h3><code>bindForeignMethodFn</code> <a href="#bindforeignmethodfn" name="bindforeignmethodfn" class="header-anchor">#</a></h3>
<p>The callback Wren uses to find a foreign method and bind it to a class. See
<a href="/embedding/calling-c-from-wren.html">this page</a> for details. If your application defines no foreign
methods, you can leave this <code>NULL</code>. </p>
<h3><code>bindForeignClassFn</code> <a href="#bindforeignclassfn" name="bindforeignclassfn" class="header-anchor">#</a></h3>
<p>The callback Wren uses to find a foreign class and get its foreign methods. See
<a href="/embedding/storing-c-data.html">this page</a> for details. If your application defines no foreign
classes, you can leave this <code>NULL</code>. </p>
<h2>Diagnostics <a href="#diagnostics" name="diagnostics" class="header-anchor">#</a></h2>
<p>These let you wire up some minimal output so you can tell if your code is doing
what you expect. </p>
<h3><code>writeFn</code> <a href="#writefn" name="writefn" class="header-anchor">#</a></h3>
<p>This is the callback Wren uses to output text when <code>System.print()</code> or the other
related functions are called. This is the minimal connection the VM has with the
outside world and lets you do rudimentary &ldquo;printf debugging&rdquo;. Its signature is: </p>
<div class="codehilite"><pre><span></span><span class="kt">void</span> <span class="n">write</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">text</span><span class="p">)</span>
</pre></div>
<p>Wren does <em>not</em> have a default implementation for this. It&rsquo;s up to you to wire
it up to <code>printf()</code> or some other way to show the text. If you leave it <code>NULL</code>,
calls to <code>System.print()</code> and others silently do nothing. </p>
<h3><code>errorFn</code> <a href="#errorfn" name="errorfn" class="header-anchor">#</a></h3>
<p>Wren uses this callback to report compile time and runtime errors. Its signature
is: </p>
<div class="codehilite"><pre><span></span><span class="kt">void</span> <span class="n">error</span><span class="p">(</span>
<span class="n">WrenErrorType</span> <span class="n">type</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">line</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">message</span><span class="p">)</span>
</pre></div>
<p>The <code>type</code> parameter is one of: </p>
<div class="codehilite"><pre><span></span><span class="k">typedef</span> <span class="k">enum</span>
<span class="p">{</span>
<span class="c1">// A syntax or resolution error detected at compile time.</span>
<span class="n">WREN_ERROR_COMPILE</span><span class="p">,</span>
<span class="c1">// The error message for a runtime error.</span>
<span class="n">WREN_ERROR_RUNTIME</span><span class="p">,</span>
<span class="c1">// One entry of a runtime error&#39;s stack trace.</span>
<span class="n">WREN_ERROR_STACK_TRACE</span>
<span class="p">}</span> <span class="n">WrenErrorType</span><span class="p">;</span>
</pre></div>
<p>When a compile error occurs, <code>errorFn</code> is called once with type
<code>WREN_ERROR_COMPILE</code>, the name of the module and line where the error occurs,
and the error message. </p>
<p>Runtime errors include stack traces. To handle this, Wren first calls <code>errorFn</code>
with <code>WREN_ERROR_RUNTIME</code>, no module or line, and the runtime error&rsquo;s message.
After that, it calls <code>errorFn</code> again using type <code>WREN_ERROR_STACK_TRACE</code>, once
for each line in the stack trace. Each of those calls has the module and line
where the method or function is defined and <code>message</code> is the name of the method
or function. </p>
<p>If you leave this <code>NULL</code>, Wren does not report any errors. </p>
<h2>Memory Management <a href="#memory-management" name="memory-management" class="header-anchor">#</a></h2>
<p>These fields control how the VM allocates and manages memory. </p>
<h3><code>reallocateFn</code> <a href="#reallocatefn" name="reallocatefn" class="header-anchor">#</a></h3>
<p>This lets you provide a custom memory allocation function. Its signature is: </p>
<div class="codehilite"><pre><span></span><span class="kt">void</span><span class="o">*</span> <span class="n">reallocate</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">memory</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">newSize</span><span class="p">)</span>
</pre></div>
<p>Wren uses this one function to allocate, grow, shrink, and deallocate memory.
When called, <code>memory</code> is the existing pointer to the block of memory if an
allocation is being changed or freed. If Wren is requesting new memory, then
<code>memory</code> is <code>NULL</code>. </p>
<p><code>newSize</code> is the number of bytes of memory being requested. If memory is being
freed, this is zero. Your callback should allocate the proper amount of memory
and return it. </p>
<p>If you don&rsquo;t provide a custom allocator, the VM uses a default one that relies
on <code>realloc</code> and <code>free</code>. </p>
<h3><code>initialHeapSize</code> <a href="#initialheapsize" name="initialheapsize" class="header-anchor">#</a></h3>
<p>This defines the total number of bytes of memory the VM will allocate before
triggering the first garbage collection. Setting this to a smaller number
reduces the amount of memory Wren will have allocated at one time, but causes it
to collect garbage more frequently. </p>
<p>If you set this to zero, Wren uses a default size of 10MB. </p>
<h3><code>minHeapSize</code> <a href="#minheapsize" name="minheapsize" class="header-anchor">#</a></h3>
<p>After a garbage collection occurs, the threshold for the <em>next</em> collection is
determined based on the number of bytes remaining in use. This allows Wren to
grow or shrink its memory usage automatically based on how much memory is
actually needed. </p>
<p>This can be used to ensure that the heap does not get <em>too</em> small, which can
in turn lead to a large number of collections afterwards as the heap grows
back to a usable size. </p>
<p>If zero, this defaults to 1MB. </p>
<h3><code>heapGrowthPercent</code> <a href="#heapgrowthpercent" name="heapgrowthpercent" class="header-anchor">#</a></h3>
<p>Wren tunes the rate of garbage collection based on how much memory is still in
use after a collection. This number controls that. It determines the amount of
additional memory Wren will use after a collection, as a percentage of the
current heap size. </p>
<p>For example, say that this is 50. After a garbage collection, there are 400
bytes of memory still in use. That means the next collection will be triggered
after a total of 600 bytes are allocated (including the 400 already in use.) </p>
<p>Setting this to a smaller number wastes less memory, but triggers more
frequent garbage collections. </p>
<p>If set to zero, the VM uses a default of 50. </p>
<p><a href="storing-c-data.html">&larr; Storing C Data</a> </p>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/munificent/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/munificent/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>