⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 201613 in webkit


Ignore:
Timestamp:
Jun 2, 2016, 1:05:08 PM (10 years ago)
Author:
fpizlo@apple.com
Message:

Fix typos and make some revisions to the B3 docs
https://bugs.webkit.org/show_bug.cgi?id=158311

Reviewed by Michael Saboff.

I found typos and fixed them. Also, I clarified some things:

  • Is B3 IR platform-agnostic? Sort of. I tried to describe when it is (Values usually behave the same way regardless of CPU) and when it isn't (it lets you speak of registers if that's what you want to do, for example).


  • How does isValidForm really get used? You don't really need to create an Inst to use it.


  • Some other incremental improvements to make the docs clearer.
  • docs/b3/assembly-intermediate-representation.html:
  • docs/b3/index.html:
  • docs/b3/intermediate-representation.html:
Location:
trunk/Websites/webkit.org
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Websites/webkit.org/ChangeLog

    r201527 r201613  
     12016-06-02  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Fix typos and make some revisions to the B3 docs
     4        https://bugs.webkit.org/show_bug.cgi?id=158311
     5
     6        Reviewed by Michael Saboff.
     7       
     8        I found typos and fixed them. Also, I clarified some things:
     9       
     10        - Is B3 IR platform-agnostic? Sort of. I tried to describe when it is (Values usually behave
     11          the same way regardless of CPU) and when it isn't (it lets you speak of registers if that's
     12          what you want to do, for example).
     13       
     14        - How does isValidForm really get used? You don't really need to create an Inst to use it.
     15       
     16        - Some other incremental improvements to make the docs clearer.
     17
     18        * docs/b3/assembly-intermediate-representation.html:
     19        * docs/b3/index.html:
     20        * docs/b3/intermediate-representation.html:
     21
    1222016-05-31  Filip Pizlo  <fpizlo@apple.com>
    223
  • trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html

    r201527 r201613  
    4545    <p>B3 is designed to be portable to many kinds of CPUs. Currently, it supports x86-64 and ARM64,
    4646      which are quite different from each other. In B3 IR, we expose very few instruction set
    47       details. Most clients only have to worry about the pointer type varying between Int32 and
    48       Int64. It's a goal of B3 IR to ensure that B3 values behave the same way except when the
    49       alternative would be prohibitive (like with pointer size or the corner-case behaviors of
    50       division). But to effectively compile code to different CPUs, the compiler has to eventually
    51       make instruction set details explicit. This is where Air comes in. B3 locks in most
    52       CPU-specific details at the moment of conversion to Air, and the Air code is irreversibly tied
    53       to some specific CPU.</p>
     47      details. It's a goal of B3 IR to ensure that B3 values behave the same way except when the
     48      alternative would be counterproductive (like with pointer size, the corner-case behaviors of
     49      division, or calling convention customization). But to effectively compile code to different
     50      CPUs, the compiler has to eventually make instruction set details explicit. This is where Air
     51      comes in. B3 locks in most CPU-specific details at the moment of conversion to Air, and the Air
     52      code is irreversibly tied to some specific CPU.</p>
    5453   
    5554    <p>Air is an instruction <i>superset</i>: it recognizes all of the instructions from all CPUs
     
    6160      and abstract
    6261      <a href="http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h">stack
    63         slots</a>.</p>
     62        slots</a>. A <code>Tmp</code> object can either hold an unallocated temporary or a
     63      register.</p>
    6464   
    6565    <h3>Air as an Instruction Superset</h3>
    66     <p>It is possible to speak of an x86-64 instruction while compiling for ARM64,
    67       for example. Clients of Air, such as the B3 to Air lowering phase, are allowed to pick with any
    68       Air opcode and ask if that opcode would be valid on the current CPU. They are also allowed to
    69       check if specific forms of any given opcode are valid. This allows clients to optimize for
    70       multiple instruction sets by cascading through the possible opcodes that they know of, starting
    71       with the one they think is most efficient. Some of those opcodes may only be available on one
    72       CPU while others are available everywhere.</p>
     66    <p>Air has syntax to speak of all of the CPU instructions we know about. It is possible to speak
     67      of an x86-64 instruction while compiling for ARM64, for example. Clients of Air, such as the B3
     68      to Air lowering phase, are allowed to pick any Air opcode and ask if that opcode would be
     69      valid on the current CPU. They are also allowed to check if specific forms of any given opcode
     70      are valid. This allows clients to optimize for multiple instruction sets by cascading through
     71      the possible opcodes that they know of, starting with the one they think is most efficient.
     72      Some of those opcodes may only be available on one CPU while others are available
     73      everywhere. Instruction selection does not need to know which instructions work on which CPUs;
     74      Air will tell you if some instruction happens to not be valid right now for whatever reason.</p>
    7375   
    7476    <p>Air opcodes support overloading. For example, the Add32 opcode has both two-operand and
    75       three-operand overloads, and those overloads have multiple forms: the first operand may or
    76       may not be an immediate and depending on the CPU, some of the other operands may or may not
    77       be memory addresses. A fundamental Air operation is <code>Inst::isValidForm()</code>, which
    78       tells the client if the instruction's current form is valid on the current CPU. This may
    79       return false either because the Inst is not well-formed for any CPU or because it is not
    80       valid for the current CPU even though it may be valid on some other CPU. This allows clients
    81       to generate Air by experimenting with various different instruction forms before settling on
    82       the one that the current CPU supports.</p>
     77      three-operand <i>overloads</i>, and those overloads have multiple <i>forms</i>: the first
     78      operand may or may not be permitted to be an immediate and depending on the CPU and some of the
     79      other operands may or may not be allowed to be memory addresses. We use <i>opcode overload</i>
     80      to refer to all forms of an opcode that share the same number of arguments, and <i>opcode
     81        form</i> to mean the number of arguments and their types. A fundamental Air operation is
     82      <code>Inst::isValidForm()</code>, which tells the client if the instruction's current form is
     83      valid on the current CPU. This may return false either because the Inst is not well-formed for
     84      any CPU or because it is not valid for the current CPU even though it may be valid on some
     85      other CPU. There is also <code>Air::isValidForm()</code>, which can answer if the form you are
     86      intending to use will be valid even if you have not created an <code>Inst</code> yet. This
     87      allows clients to generate Air by experimenting with different forms before settling on the one
     88      that the current CPU supports.</p>
    8389   
    8490    <h3>Air as a High-Level Assembly</h3>
     
    94100      Air code.</p>
    95101   
    96     <p>Air's philosophy allows B3 to use it for converting high-level, CPU-agnostic SSA procedures
    97       into code for the current CPU. Air is an instruction superset that allows clients to consider
    98       all available instructions on all possible CPUs and query which forms of those instructions are
    99       available on the current CPU. Air also supports for high-level concepts like <code>Tmp</code>s
    100       and stack slots, which allows B3 to Air lowering to focus on which instructions to use without
    101       worrying about register allocation or stack layout.</p>
     102    <p>Air's philosophy allows B3 to use it for converting high-level, mostly-CPU-agnostic SSA
     103      procedures into code for the current CPU. Air is an instruction superset that allows clients to
     104      consider all available instructions on all possible CPUs and query which forms of those
     105      instructions are available on the current CPU. Air also supports for high-level concepts like
     106      <code>Tmp</code>s and stack slots, which allows B3 to Air lowering to focus on which
     107      instructions to use without worrying about register allocation or stack layout.</p>
    102108   
    103109    <h2>Args and the Air Execution Model</h2>
     
    108114      write to them, for example. Orthognality implies that any argument that is read may be either
    109115      a register (or <code>Tmp</code>), an address, or an immediate; while any argument that is
    110       written may be either a register or an address. Air constraints orthognality where the target
     116      written may be either a register or an address. Air constrains orthognality where the target
    111117      CPU would. For example, none of Air's target CPUs would support an <code>Add32</code>
    112118      instruction that loads its sources from memory <i>and</i> stores its result into memory. Even
     
    187193    </ol>
    188194   
    189     <p>Note that the early actions of one instruction happen immediately after the late actions of
     195    <p>The early actions of one instruction happen immediately after the late actions of
    190196      the instruction before it. However, many Air analyses view them as happening at the same time.
    191       For example, any register usage in the early action of one instruction interfere with the
     197      For example, any register usage in the early action of one instruction interferes with the
    192198      register usage in the late action of the instruction that came before it. All of Air's
    193199      liveness and interference analyses reason about the
     
    246252    </ol>
    247253   
     254    <p>Air's introspection of <code>Inst</code>s tends to be quite fast thanks to the use of template
     255      specialization and C++ lambdas. The <code>forEachArg()</code> template method uses an efficient
     256      arrangement of switch statements to determine the opcode and overload. If <code>func</code> is
     257      a C++ lambda, we expect <code>forEachArg()</code> to be specialized for that lambda. Therefore,
     258      this idiom avoids virtual dispatch or memory allocation.</p>
     259   
    248260    <p>Air supports exotic roles, such as late uses and early defs. There is even the
    249261      <code>Scratch</code> role, which means early def and late use. Speaking of a <code>Tmp</code>
    250262      in the <code>Scratch</code> role means that the <code>Tmp</code> will be assigned a register
    251263      that is guaranteed to not interfere with any of the other registers that the instruction
    252       speaks of. Late uses and early defs are crucial for patchpoints, which may for example require
     264      speaks of. Late uses and early defs are crucial for patchpoints, which may require
    253265      that one of the incoming values be given a register that does not interfere with whatever
    254266      register is used for the result. This can be expressed either as giving the inputs a late use
     
    300312      late actions is determined by the opcode and the number of arguments (i.e. the overload).
    301313      Clients of Air may create an <code>Inst</code> with any combination of opcode and arguments
    302       and then query, using <code>Inst::isValidForm()</code> if the opcode, overload, and specific
     314      and then query, using <code>isValidForm()</code> if the opcode, overload, and specific
    303315      arguments are valid for the current CPU.</p>
    304316   
     
    345357      CPUs, such as x86 or x86-64.</p>
    346358   
     359    <p>Air opcodes are designed to work with JavaScriptCore's existing MacroAssembler. By default, an
     360      opcode is automatically given a code generator that calls
     361      <code>MacroAssembler::<i>opcodeName</i></code>, where <i>opcodeName</i> is derived by
     362      lower-casing the first letter of the Air opcode name. <code>Add32</code> becomes
     363      <code>MacroAssembler::add32</code>, for example.</p>
     364   
    347365    <p>See the header of
    348366      <a href="http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes">AirOpcode.opcodes</a>
  • trunk/Websites/webkit.org/docs/b3/index.html

    r196029 r201613  
    3131      its argument and returns it:</p>
    3232
    33     <pre><code>Procedure proc;
     33    <pre><code>// Create a Procedure that holds our code.
     34Procedure proc;
    3435BasicBlock* root = proc.addBlock();
    3536root->appendNew&lt;ControlValue&gt;(
     
    4041        root->appendNew<Const64Value>(proc, Origin(), 2)));
    4142
     43// Have B3 compile the Procedure into code. The code and all of its artifacts (constant pools, jump tables)
     44// will stay alive so long as Compilation stays alive.
    4245std::unique_ptr&lt;Compilation&gt; compilation = std::make_unique&lt;Compilation&gt;(vm, proc);
     46
     47// Get a function pointer that we can call. This function pointer points to JIT-generated machine code.
    4348int64_t (*function)(int64_t) = bitwise_cast&lt;int64_t (*)(int64_t)&gt;(compilation->code().executableAddress());
    4449
    45 printf("%lld\n", function(42)); // prints 44</code></pre>
     50// Run it and print the result!
     51printf("%lld\n", function(42)); // Prints 44.</code></pre>
    4652
    4753    <p>When compiled, the resulting machine code looks like this:</p>
     
    6369      <a href="intermediate-representation.html">B3 IR</a>.  It's C-like, in the sense that it
    6470      models heap references as integers and does not attempt to verify memory accesses.  It
    65       enforces static single assignment, or SSA for short.  An SSA program will contain only one
    66       assignment to each variable, which makes it trivial to trace from a use of a variable to
    67       the operation that defined its value.  B3 IR is designed to be easy to generate and cheap
    68       to manipulate.</p>
    69 
    70     <p>B3 is designed to be used as a backend for JITs, rather than as a tool that programmers
    71       use directly.  Therefore, B3 embraces platform-specific concepts like argument registers,
    72       stack frame layout, the frame pointer, and the call argument areas.  It's possible to emit
    73       B3 IR that defines completely novel calling conventions, both for callers of the procedure
    74       being generated and for callees of the procedure's callsites.  B3 also makes it easy to
    75       just emit a C call.  There's an opcode for that.</p>
     71      enforces <a href="https://en.wikipedia.org/wiki/Static_single_assignment_form">static single
     72        assignment</a>, or SSA for short.  An SSA program will contain only one assignment to each
     73      variable, which makes it trivial to trace from a use of a variable to the operation that
     74      defined its value.  B3 IR is designed to be easy to generate and cheap to manipulate.</p>
     75
     76    <p>In most ways, B3 IR is platform-agnostic. However, since B3 is designed to be used as a
     77      backend for JITs, it does embrace some platform-specific concepts whenever it is pragmatic to
     78      do so. B3 exposes direct control over argument registers, stack frame layout, the frame
     79      pointer, and the call argument areas.  It's possible to emit B3 IR that defines completely
     80      novel calling conventions, both for callers of the procedure being generated and for callees of
     81      the procedure's callsites.  B3 also makes it easy to just emit a C call.  There's an opcode for
     82      that.</p>
    7683
    7784    <p>See <a href="intermediate-representation.html">the IR documentation</a> for more
     
    147154    Ret64 %rax, @3</code></pre>
    148155
    149     <h2>B3->Air lowering, also known as Instruction Selection</h2>
     156    <h2>B3&rarr;Air lowering, also known as Instruction Selection</h2>
    150157
    151158    <p>The B3::LowerToAir phase converts B3 into Air by doing pattern-matching.  It processes
     
    194201    <h2>Code generation</h2>
    195202
    196     <p>The final form of Air contains no registers or abstract stack slots.  Therefore, it maps
    197       directly to machine code.  The final code generation step is a very fast transformation
     203    <p>The final form of Air contains no unallocated temporaries or abstract stack slots.  Therefore,
     204      it maps directly to machine code.  The final code generation step is a very fast transformation
    198205      from Air's object-oriented way of representing those instructions to the target's machine
    199206      code.  We use JavaScriptCore's macro assembler for this purpose.</p>
  • trunk/Websites/webkit.org/docs/b3/intermediate-representation.html

    r197380 r201613  
    6666    </dl>
    6767
     68    <p>B3 does not have a pointer type. Instead, the <code>B3::pointerType()</code> function will
     69      return either Int32 or Int64 depending on which kind of integer can be used to represent a
     70      pointer on the current platform. It's not a goal of B3 to support hardware targets that require
     71      pointers and integers to be segregated. It's not a goal of B3 to support GC (garbage
     72      collection) roots as a separate type, since JSC uses
     73      <a href="http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-88-2.pdf">Bartlett-style conservative
     74        root scanning</a>. This doesn't preclude any mainstream garbage collection algorithms,
     75      including copying, generational, or concurrent collectors, and frees up the compiler to perform
     76      more optimizations.</p>
     77
    6878    <h2>Values</h2>
    6979
     
    413423
    414424      <dt>T1 Patchpoint([T2, [T3, ...]])</dt>
    415       <dd>A Patchpoint is a customizable value.  Patchpoints take zero or more values of any
    416         type and return any type.  A Patchpoint's behavior is determined by the generator
    417         object.  The generator is a C++ lambda that gets called during code generation.  It gets
    418         passed an assembler instance (specifically, CCallHelpers&) and an object describing
    419         where to find all of the input values and where to put the result.  Here's an example:
     425      <dd>
     426        <p>A Patchpoint is a customizable value.  Patchpoints take zero or more values of any
     427          type and return any type.  A Patchpoint's behavior is determined by the generator
     428          object.  The generator is a C++ lambda that gets called during code generation.  It gets
     429          passed an assembler instance (specifically, CCallHelpers&) and an object describing
     430          where to find all of the input values and where to put the result.  Here's an example:</p>
    420431 
    421432        <pre><code>PatchpointValue* patchpoint = block->appendNew&lt;PatchpointValue&gt;(proc, Int32, Origin());
Note: See TracChangeset for help on using the changeset viewer.