Angelscript/docs/manual/doc_adv_jit.html

211 lines
18 KiB
HTML
Raw Permalink Normal View History

2021-04-12 18:25:02 +00:00
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AngelScript: How to build a JIT compiler</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">AngelScript
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('doc_adv_jit.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">How to build a JIT compiler </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>AngelScript doesn't provide a built-in JIT compiler, instead it permits an external JIT compiler to be implemented through a public interface.</p>
<p>To use JIT compilation, the scripts must be compiled with a few extra instructions that provide hints to the JIT compiler and also entry points so that the VM will know when to pass control to the JIT compiled function. By default this is turned off, and must thus be turned on by setting the engine property <a class="el" href="angelscript_8h.html#a53c2e8a74ade77c928316396394ebe0fa7ff74f4afa490b55839daaf217cf898c">asEP_INCLUDE_JIT_INSTRUCTIONS</a>.</p>
<p>If the application sets the <a class="el" href="classas_i_j_i_t_compiler.html">JIT compiler</a> with <a class="el" href="classas_i_script_engine.html#aee4f910163604203a27db1ffea3b1c9c">SetJITCompiler</a> AngelScript will automatically invoke it to provide the <a class="el" href="angelscript_8h.html#af9d3986a33c1bda5c4f82a7aaa0dfeeb">JIT functions</a> with each compilation or <a class="el" href="doc_adv_precompile.html">loading of pre-compiled bytecode</a>.</p>
<h1><a class="anchor" id="doc_adv_jit_3"></a>
The structure of the JIT function</h1>
<p>The <a class="el" href="angelscript_8h.html#af9d3986a33c1bda5c4f82a7aaa0dfeeb">JIT compiled function</a> must follow certain rules in order to behave well with the virtual machine. The intention is that the VM will pass the control to the JIT function, and when the execution is to be suspended the JIT function returns the control to the VM, updating the internal state of the VM so that the VM can resume the execution when requested. Each time the JIT function returns control to the VM it must make sure that the <a class="el" href="structas_s_v_m_registers.html">VM registers</a> and stack values have been updated according to the code that was executed.</p>
<p>The byte code will have a special instruction, <a class="el" href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0a6705ee9692b45f118cfe0ea24581fae5">JitEntry</a>, which defines the positions where the VM can pass the control to the JIT function. These are usually placed for every script statement, and after each instruction that calls another function. This implies that the JIT compiled function needs to be able to start the execution at different points based on the argument in the JitEntry instruction. The value of the argument is defined by the JIT compiler and how it is interpreted is also up to the JIT compiler, with the exception of 0 that means that the control should not be passed to the JIT function.</p>
<p>Some byte code instructions are not meant to be converted into native code. These are usually the ones that have a more global effect on the VM, e.g. the instructions that setup a call to a new script function, or that return from a previous instruction. When these functions are encountered, the JIT function should return the control to the VM, and then the VM will execute the instruction.</p>
<p>Other byte code instructions may be partially implemented by the JIT function, for example those that can throw an exception based on specific conditions. One such example is the instructions for divisions, if the divider is 0 the VM will set an exception and abort the execution. For these instructions the JIT compiler should preferrably implement the condition that doesn't throw an exception, and if an exception is to be thrown the JIT function will instead break out to the VM.</p>
<p>The following shows a possible structure of a JIT compiled function:</p>
<pre>
void jitCompiledFunc(asSVMRegisters *regs, asPWORD jitArg)
{
Read desired VM registers into CPU registers.
Jump to the current position of the function based on the 'jitArg' argument.
1:
Execute code in block 1.
Jump to exit if an illegal operation is done, e.g. divide by zero.
Jump to exit if block ends with an instruction that should not be executed by JIT function.
2:
...
3:
...
exit:
Update the VM registers before returning control to VM.
If necessary the function can invoke the methods of the context informed
in the regs, e.g. to suspend the execution, or to set a script exception.
}
</pre><h1><a class="anchor" id="doc_adv_jit_2"></a>
Traversing the byte code</h1>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> CJITCompiler::CompileFunction(<a class="code" href="classas_i_script_function.html">asIScriptFunction</a> *func, <a class="code" href="angelscript_8h.html#af9d3986a33c1bda5c4f82a7aaa0dfeeb">asJITFunction</a> *output)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">bool</span> success = StartNewCompilation();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Get the script byte code</span></div>
<div class="line"> <a class="code" href="angelscript_8h.html#ac8186f029686800b7ce36bde4a55c815">asUINT</a> length;</div>
<div class="line"> <a class="code" href="angelscript_8h.html#a5428f0c940201e5f3bbb28304aeb81bc">asDWORD</a> *byteCode = func-&gt;<a class="code" href="classas_i_script_function.html#afb38e9ba77ce8b49378e43dadd83ef94">GetByteCode</a>(&amp;length);</div>
<div class="line"> <a class="code" href="angelscript_8h.html#a5428f0c940201e5f3bbb28304aeb81bc">asDWORD</a> *end = byteCode + length;</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">while</span>( byteCode &lt; end )</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Determine the instruction</span></div>
<div class="line"> <a class="code" href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0">asEBCInstr</a> op = <a class="code" href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0">asEBCInstr</a>(*(<a class="code" href="angelscript_8h.html#a48b3da7121b3abb56bff63b3beb0df63">asBYTE</a>*)byteCode);</div>
<div class="line"> <span class="keywordflow">switch</span>( op )</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Translate each byte code instruction into native code.</span></div>
<div class="line"> <span class="comment">// The codes that cannot be translated should return the control</span></div>
<div class="line"> <span class="comment">// to the VM, so that it can continue the processing. When </span></div>
<div class="line"> <span class="comment">// the VM encounters the next JitEntry instruction it will</span></div>
<div class="line"> <span class="comment">// transfer the control back to the JIT function.</span></div>
<div class="line"> ...</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">case</span> <a class="code" href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0a6705ee9692b45f118cfe0ea24581fae5">asBC_JitEntry</a>:</div>
<div class="line"> <span class="comment">// Update the argument for the JitEntry instruction with </span></div>
<div class="line"> <span class="comment">// the argument that should be sent to the jit function.</span></div>
<div class="line"> <span class="comment">// Remember that 0 means that the VM should not pass</span></div>
<div class="line"> <span class="comment">// control to the JIT function.</span></div>
<div class="line"> <a class="code" href="angelscript_8h.html#aac9eb586274fc44bb1b838d833963996">asBC_PTRARG</a>(byteCode) = DetermineJitEntryArg();</div>
<div class="line"> <span class="keywordflow">break</span>;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Move to next instruction</span></div>
<div class="line"> byteCode += <a class="code" href="angelscript_8h.html#a9f93754a6f4d43118cd0d2b3896875a5">asBCTypeSize</a>[<a class="code" href="angelscript_8h.html#ac58d23b688ddd6d6e788b034daf25df7">asBCInfo</a>[op].<a class="code" href="structas_s_b_c_info.html#aa0579956f325760177250e0eddd52ab4">type</a>];</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">if</span>( success )</div>
<div class="line"> {</div>
<div class="line"> *output = GetCompiledFunction();</div>
<div class="line"> <span class="keywordflow">return</span> 0;</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">return</span> -1;</div>
<div class="line">}</div>
</div><!-- fragment --><p>The following macros should be used to read the arguments from the bytecode instruction. The layout of the arguments is determined from the <a class="el" href="angelscript_8h.html#ac58d23b688ddd6d6e788b034daf25df7">asBCInfo</a> array.</p>
<ul>
<li><a class="el" href="angelscript_8h.html#a7b3dbfcc3928ddd853a4ee53cbc13b69">asBC_DWORDARG</a></li>
<li><a class="el" href="angelscript_8h.html#a290586f7a153d5e8717b01680262b667">asBC_INTARG</a></li>
<li><a class="el" href="angelscript_8h.html#a92e1437ea399e8c545e15bffd651f45f">asBC_QWORDARG</a></li>
<li><a class="el" href="angelscript_8h.html#a0183edd413564ff4897eb4a2473d01f6">asBC_FLOATARG</a></li>
<li><a class="el" href="angelscript_8h.html#aac9eb586274fc44bb1b838d833963996">asBC_PTRARG</a></li>
<li><a class="el" href="angelscript_8h.html#a942798ec89a8ac96550523d80570c703">asBC_WORDARG0</a></li>
<li><a class="el" href="angelscript_8h.html#a0a704bf4db31deda2a69d3216312618c">asBC_WORDARG1</a></li>
<li><a class="el" href="angelscript_8h.html#a2287157faea7f6d32b316c17e0858ddf">asBC_SWORDARG0</a></li>
<li><a class="el" href="angelscript_8h.html#a92601565873cf5d29a6876c2638d7fec">asBC_SWORDARG1</a></li>
<li><a class="el" href="angelscript_8h.html#a698449bbbe369b8a479fb0dd82c9b18e">asBC_SWORDARG2</a></li>
</ul>
<p>What each <a class="el" href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0">byte code</a> instruction does is described in <a class="el" href="doc_adv_jit_1.html">Byte code instructions</a>, but the exact implementation of each byte code instruction is best determined from the implementation in the VM, i.e. the asCScriptContext::ExecuteNext method. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div class="ttc" id="aangelscript_8h_html_a5428f0c940201e5f3bbb28304aeb81bc"><div class="ttname"><a href="angelscript_8h.html#a5428f0c940201e5f3bbb28304aeb81bc">asDWORD</a></div><div class="ttdeci">unsigned long asDWORD</div><div class="ttdoc">32 bit unsigned integer</div><div class="ttdef"><b>Definition:</b> angelscript.h:614</div></div>
<div class="ttc" id="aangelscript_8h_html_ac58d23b688ddd6d6e788b034daf25df7"><div class="ttname"><a href="angelscript_8h.html#ac58d23b688ddd6d6e788b034daf25df7">asBCInfo</a></div><div class="ttdeci">const asSBCInfo asBCInfo[256]</div><div class="ttdoc">Information on each bytecode instruction.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4884</div></div>
<div class="ttc" id="aangelscript_8h_html_ab3692c4e5d47fc93f8c9646d1783aef0"><div class="ttname"><a href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0">asEBCInstr</a></div><div class="ttdeci">asEBCInstr</div><div class="ttdoc">The bytecode instructions used by the VM.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4351</div></div>
<div class="ttc" id="aangelscript_8h_html_a48b3da7121b3abb56bff63b3beb0df63"><div class="ttname"><a href="angelscript_8h.html#a48b3da7121b3abb56bff63b3beb0df63">asBYTE</a></div><div class="ttdeci">unsigned char asBYTE</div><div class="ttdoc">8 bit unsigned integer</div><div class="ttdef"><b>Definition:</b> angelscript.h:598</div></div>
<div class="ttc" id="aangelscript_8h_html_af9d3986a33c1bda5c4f82a7aaa0dfeeb"><div class="ttname"><a href="angelscript_8h.html#af9d3986a33c1bda5c4f82a7aaa0dfeeb">asJITFunction</a></div><div class="ttdeci">void(* asJITFunction)(asSVMRegisters *registers, asPWORD jitArg)</div><div class="ttdoc">The function signature of a JIT compiled function.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4316</div></div>
<div class="ttc" id="aangelscript_8h_html_ab3692c4e5d47fc93f8c9646d1783aef0a6705ee9692b45f118cfe0ea24581fae5"><div class="ttname"><a href="angelscript_8h.html#ab3692c4e5d47fc93f8c9646d1783aef0a6705ee9692b45f118cfe0ea24581fae5">asBC_JitEntry</a></div><div class="ttdeci">@ asBC_JitEntry</div><div class="ttdoc">If a JIT function is available and the argument is not 0 then call the JIT function.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4703</div></div>
<div class="ttc" id="aclassas_i_script_function_html_afb38e9ba77ce8b49378e43dadd83ef94"><div class="ttname"><a href="classas_i_script_function.html#afb38e9ba77ce8b49378e43dadd83ef94">asIScriptFunction::GetByteCode</a></div><div class="ttdeci">virtual asDWORD * GetByteCode(asUINT *length=0)=0</div><div class="ttdoc">Returns the byte code buffer and length.</div></div>
<div class="ttc" id="aangelscript_8h_html_ac8186f029686800b7ce36bde4a55c815"><div class="ttname"><a href="angelscript_8h.html#ac8186f029686800b7ce36bde4a55c815">asUINT</a></div><div class="ttdeci">unsigned int asUINT</div><div class="ttdoc">32 bit unsigned integer</div><div class="ttdef"><b>Definition:</b> angelscript.h:600</div></div>
<div class="ttc" id="aclassas_i_script_function_html"><div class="ttname"><a href="classas_i_script_function.html">asIScriptFunction</a></div><div class="ttdoc">The interface for a script function description.</div><div class="ttdef"><b>Definition:</b> angelscript.h:3823</div></div>
<div class="ttc" id="aangelscript_8h_html_a9f93754a6f4d43118cd0d2b3896875a5"><div class="ttname"><a href="angelscript_8h.html#a9f93754a6f4d43118cd0d2b3896875a5">asBCTypeSize</a></div><div class="ttdeci">const int asBCTypeSize[21]</div><div class="ttdoc">Lookup table for determining the size of each type of bytecode instruction.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4815</div></div>
<div class="ttc" id="aangelscript_8h_html_aac9eb586274fc44bb1b838d833963996"><div class="ttname"><a href="angelscript_8h.html#aac9eb586274fc44bb1b838d833963996">asBC_PTRARG</a></div><div class="ttdeci">#define asBC_PTRARG(x)</div><div class="ttdoc">Macro to access the first pointer argument in the bytecode instruction.</div><div class="ttdef"><b>Definition:</b> angelscript.h:5156</div></div>
<div class="ttc" id="astructas_s_b_c_info_html_aa0579956f325760177250e0eddd52ab4"><div class="ttname"><a href="structas_s_b_c_info.html#aa0579956f325760177250e0eddd52ab4">asSBCInfo::type</a></div><div class="ttdeci">asEBCType type</div><div class="ttdoc">Instruction argument layout.</div><div class="ttdef"><b>Definition:</b> angelscript.h:4855</div></div>
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated on Sat Dec 5 2020 23:20:24 for AngelScript by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
</ul>
</div>
</body>
</html>