Instruction-Stacks.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <html lang="en">
  2. <head>
  3. <title>Instruction Stacks - avram - a virtual machine code interpreter</title>
  4. <meta http-equiv="Content-Type" content="text/html">
  5. <meta name="description" content="avram - a virtual machine code interpreter">
  6. <meta name="generator" content="makeinfo 4.13">
  7. <link title="Top" rel="start" href="index.html#Top">
  8. <link rel="up" href="Emulation-Primitives.html#Emulation-Primitives" title="Emulation Primitives">
  9. <link rel="prev" href="Ports-and-Packets.html#Ports-and-Packets" title="Ports and Packets">
  10. <link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
  11. <meta http-equiv="Content-Style-Type" content="text/css">
  12. <style type="text/css"><!--
  13. pre.display { font-family:inherit }
  14. pre.format { font-family:inherit }
  15. pre.smalldisplay { font-family:inherit; font-size:smaller }
  16. pre.smallformat { font-family:inherit; font-size:smaller }
  17. pre.smallexample { font-size:smaller }
  18. pre.smalllisp { font-size:smaller }
  19. span.sc { font-variant:small-caps }
  20. span.roman { font-family:serif; font-weight:normal; }
  21. span.sansserif { font-family:sans-serif; font-weight:normal; }
  22. --></style>
  23. </head>
  24. <body>
  25. <div class="node">
  26. <a name="Instruction-Stacks"></a>
  27. <p>
  28. Previous:&nbsp;<a rel="previous" accesskey="p" href="Ports-and-Packets.html#Ports-and-Packets">Ports and Packets</a>,
  29. Up:&nbsp;<a rel="up" accesskey="u" href="Emulation-Primitives.html#Emulation-Primitives">Emulation Primitives</a>
  30. <hr>
  31. </div>
  32. <h4 class="subsection">3.8.3 Instruction Stacks</h4>
  33. <p>A header file named <samp><span class="file">instruct.h</span></samp> declares a number of memory
  34. management and stack operations on a data structure of the following
  35. form.
  36. <a name="index-g_t_0040code_007binstruction_005fnode_007d-645"></a>
  37. <pre class="example"> struct instruction_node
  38. {
  39. port client;
  40. score sheet;
  41. struct avm_packet actor;
  42. struct avm_packet datum;
  43. instruction dependents;
  44. };
  45. </pre>
  46. <p>In this structure, an <code>instruction</code> is a pointer to an
  47. <code>instruction_node</code>, a <code>score</code> is a pointer to a profile
  48. database entry as discussed in <a href="Profiling.html#Profiling">Profiling</a>, and the <code>port</code> and
  49. <code>avm_packet</code> types are as described in <a href="Ports-and-Packets.html#Ports-and-Packets">Ports and Packets</a>.
  50. <p>This data structure is appropriate for a simple virtual machine code
  51. <a name="index-concurrency-646"></a>evaluation strategy involving no concurrency. The strategy to evaluate an
  52. expression <var>f</var> <var>x</var> would be based on a stack of these
  53. nodes threaded through the <code>dependents</code> field, and would proceed
  54. something like this.
  55. <ol type=1 start=1>
  56. <li>The stack is initialized to contain a single node having
  57. <var>f</var> in its <code>actor.contents</code> field, and <var>x</var> in
  58. its <code>datum.contents</code> field.
  59. <li>The <code>client</code> in this node would refer to a static packet to whose
  60. <code>contents</code> field the final result will be delivered.
  61. <li>The evaluator examines the <code>actor.contents</code> field on the top of the
  62. stack, detects by its form the operation it represents, and decides
  63. whether it corresponds to one that can be evaluated immediately by way
  64. of a canned function available in the library. List reversal,
  65. transposition, and comparison would be examples of such operations.
  66. <li>If the operation can be performed in this way, the result is computed
  67. and assigned to the destination indicated by the <code>client</code> field.
  68. <li>If the operation is not easy enough to perform immediately but is of a
  69. form recognizable as a combination of simpler operations, it is
  70. decomposed into the simpler operations, and each of them is
  71. strategically positioned on the stack so as to effect the evaluation of
  72. the combination. For example, if <var>f</var> were of the form
  73. <code>compose(</code><var>g</var><code>,</code><var>h</var><code>)</code> (<code>silly</code> notation), the node with
  74. <var>f</var> and <var>x</var> would be popped, but a node with
  75. <var>g</var> as its <code>actor.contents</code> would be pushed, and then a
  76. node with <var>h</var> as its <code>actor.contents</code> and <var>x</var>
  77. as its <code>datum.contents</code> would be pushed. Furthermore, the
  78. <code>client</code> field of the latter node would point to the
  79. <code>datum.contents</code> of the one with <var>g</var>, and the
  80. <code>client</code> field of the one with <var>g</var> would point
  81. wherever the <code>client</code> of the popped node used to point.
  82. <li>If the operation indicated by the top <code>actor.contents</code> is neither
  83. implemented by a canned operation in the library nor easily decomposable
  84. into some that are, the evaluator can either give up or use virtual code
  85. to execute other virtual code. The latter trick is accomplished by
  86. pushing a node with <var>f</var> as its <code>datum.contents</code>, and a
  87. copy of a hard coded virtual code interpreter <var>V</var> as its
  88. <code>actor.contents</code>. The <code>client</code> of this node will point to the
  89. <var>f</var> in the original node so as to overwrite it when a
  90. simplified version is subsequently computed. The implementation of
  91. <var>V</var> is a straightforward exercise in <code>silly</code>
  92. programming.
  93. <li>In any case, the evaluator would continue working on the stack until
  94. everything on it has been popped, at which time the result of the entire
  95. computation will be found in the packet addressed by the <code>client</code>
  96. in the original instruction node.
  97. </ol>
  98. <p>What makes this strategy feasible to implement is the assumption of a
  99. sequential language, wherein synchronization incurs no cost and is
  100. automatic. The availability of any operand is implied by its position at
  101. the top of the stack. If you are reading this section with a view to
  102. <a name="index-threads-647"></a>implementing a concurrent or multi-threaded evaluation strategy, it will
  103. be apparent that further provisions would need to be made, such as that
  104. of a <code>data_ready</code> flag added to the <code>avm_packet</code> structure.
  105. <p>The following functions support the use of stacks of instruction nodes
  106. that would be needed in an evaluation strategy such as the one above.
  107. <div class="defun">
  108. &mdash; Function: int <b>avm_scheduled</b> (<var>list actor_contents, counter datum_errors, list datum_contents, port client, instruction *next, score sheet</var>)<var><a name="index-avm_005fscheduled-648"></a></var><br>
  109. <blockquote>
  110. <p>This function performs the memory allocation for instruction nodes. It
  111. attempts to create one and to initialize the fields with the given
  112. parameters, returning a pointer to it if successful. It returns a
  113. <code>NULL</code> pointer if the storage could not be allocated.
  114. <p>Copies of the <code>list</code> parameters <code>actor_contents</code> and
  115. <code>data_contents</code> are made by this function using <code>avm_copied</code>,
  116. so the originals still exist as far as the caller is concerned and will
  117. have to be deallocated separately from this structure. The copies are
  118. made only if the allocation succeeds.
  119. <p>Any fields other than those indicated by the parameters to this function
  120. are filled with zeros in the result.
  121. </p></blockquote></div>
  122. <div class="defun">
  123. &mdash; Function: void <b>avm_retire</b> (<var>instruction *done</var>)<var><a name="index-avm_005fretire-649"></a></var><br>
  124. <blockquote><p>This function performs the storage reclamation of instructions, taking
  125. as its argument the instruction to be reclaimed. The <code>list</code> fields
  126. in the structure corresponding to the <code>list</code> parameters used when
  127. it was created are specifically reclaimed as well, using
  128. <code>avm_dispose</code>.
  129. <p>The argument to this function is the address of an <code>instruction</code>
  130. rather than just an <code>instruction</code> so that the <code>instruction</code>
  131. whose address is given may be reassigned as the <code>dependents</code> field
  132. of the deallocated node. In this way, the instructions can form a stack
  133. that is popped by this function.
  134. <p>This function cooperates with <code>avm_scheduled</code> in the use of a local
  135. cache of instruction nodes in the interest of better performance. Client
  136. modules should not attempt to allocate or reclaim instructions directly
  137. with <code>malloc</code> or <code>free</code>, but use only these functions.
  138. <p>It causes a fatal internal error to pass a <code>NULL</code> pointer to this
  139. function.
  140. </p></blockquote></div>
  141. <div class="defun">
  142. &mdash; Function: void <b>avm_reschedule</b> (<var>instruction *next</var>)<var><a name="index-avm_005freschedule-650"></a></var><br>
  143. <blockquote><p>Given the address of an instruction pointer that may be regarded as the
  144. top of a stack of instructions threaded through the <code>dependents</code>
  145. field, this function exchanges the positions of the top instruction and
  146. the one below it. A fatal internal error is caused if there are fewer
  147. than two instructions in the stack.
  148. <p>A use for this function arises in the course of evaluating virtual code
  149. applications of the form <code>conditional(</code><var>p</var><code>,(</code><var>f</var><code>,</code><var>g</var><code>))</code>
  150. (in <code>silly</code> notation). The evaluation strategy would require
  151. pushing nodes for all three constituents, but with <var>p</var> pushed
  152. last (therefore evaluated first). The result of the evaluation of
  153. <var>p</var> would require either the top one or the one below it to
  154. be popped without being evaluated, depending on whether the result is
  155. empty.
  156. </p></blockquote></div>
  157. <div class="defun">
  158. &mdash; Function: void <b>avm_initialize_instruct</b> ()<var><a name="index-avm_005finitialize_005finstruct-651"></a></var><br>
  159. <blockquote><p>This function should be called before any of the instruction memory
  160. management functions is called in order to initialize some local data
  161. structures. Results are unpredictable without it.
  162. </p></blockquote></div>
  163. <div class="defun">
  164. &mdash; Function: void <b>avm_count_instruct</b> ()<var><a name="index-avm_005fcount_005finstruct-652"></a></var><br>
  165. <blockquote><p>This function should be called after the last call to any of the
  166. other functions in this section in order to detect and report
  167. unreclaimed storage associated with them. A warning message will be
  168. written to standard error if any unreclaimed instructions remain. This
  169. function relies on the assumption that the memory management has been
  170. done only by way of the above functions.
  171. </p></blockquote></div>
  172. </body></html>