PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/doc/hackers-guide/jit-core.md

https://gitlab.com/iranjith4/hhvm
Markdown | 284 lines | 238 code | 46 blank | 0 comment | 0 complexity | 02b3eba63ff6c637166a11681e93f9cb MD5 | raw file
  1. # HHVM JIT
  2. HHVM's just-in-time compiler module is responsible for translating sequences of
  3. [HHBC](../bytecode.specification) into equivalent sequences of x86-64 or ARM64
  4. machine code. The vast majority of the code implementing the JIT lives in the
  5. namespace `HPHP::jit`, in [hphp/runtime/vm/jit](../../runtime/vm/jit). Most
  6. file and class names referenced in this document will be relative to that
  7. namespace and path.
  8. The basic assumption guiding HHVM's JIT is that while PHP is a dynamically
  9. typed language, the types flowing through PHP programs aren't very dynamic in
  10. practice. We observe the types present at runtime and generate machine code
  11. specialized to operate on these types, inserting runtime typechecks where
  12. appropriate to verify assumptions made at compile time.
  13. ## Region Selection
  14. The first step in translating HHBC into machine code is deciding exactly which
  15. code to translate, in a process called region selection. The size and shape of
  16. regions depend on many factors, ranging from a single HHBC instruction up to an
  17. entire function with complex control flow. There are a number of different ways
  18. to select a region, all producing a `RegionDesc` struct in the end (defined in
  19. [region-selection.h](../../runtime/vm/jit/region-selection.h)). `RegionDesc`
  20. contains a list of `RegionDesc::Block` structs, and each `Block` represents a
  21. basic block of bytecodes by holding a starting offset and length in
  22. instructions. The list of `Block`s is kept sorted in reverse post order. Blocks
  23. also contain optional metadata about the code they contain and the state of the
  24. VM before, during, and after execution of that code. This metadata includes
  25. type predictions, parameter reffiness predictions, statically known call
  26. destinations, and certain postconditions.
  27. ### Tracelet Region Selection
  28. The first-gear region selector is the tracelet region selector. The name
  29. "tracelet" is somewhat vestigal, and refers to a region of HHBC typically no
  30. larger than a single basic block. This code lives in
  31. [region-tracelet.cpp](../../runtime/vm/jit/region-tracelet.cpp), and its goal
  32. is to select a region given only the current live VM state - most importantly
  33. the current program counter and the types of all locals and eval stack
  34. slots. `Translator` (see the "HHIR" section) is used to simulate execution
  35. of the bytecode using types instead of values, continuing until a control flow
  36. instruction is encountered or an instruction attempts to consume a value of an
  37. unknown type. These rules are not absolute; there are a number of
  38. exceptions. If an unconditional forward Jmp is encountered, the tracelet will
  39. continue at the Jmp's destination. In addition, certain bytecodes (such as PopC
  40. and IsTypeC) are able to operate on generic values and don't cause a tracelet
  41. to terminate due to imprecise types.
  42. ### PGO and Hottrace Region Selection
  43. HHVM's JIT supports
  44. ## Region Translation
  45. ## HHIR
  46. Once a bytecode region has been selected, it is translated into [HipHop
  47. Intermediate Representation](../ir.specification), commonly referred to as
  48. HHIR. HHIR is an SSA-form, strongly-typed intermediate representation
  49. positioned between HHBC and machine code. A few different classes are involved
  50. in this translation:
  51. * `Translator`: Defined in
  52. [translator.h](../../runtime/vm/jit/translator.h), this class is used to
  53. convert a RegionDesc into a sequence of HHIR instructions.
  54. The interface for emitting HHIR code is located in
  55. [irgen.h](../../runtime/vm/jit/irgen.h) and declares roughly one `emitXXX`
  56. method for each supported HHBC instruction. The implementations for these
  57. methods are grouped into `irgen-*.cpp` files (e.g.
  58. [irgen-basic.cpp](../../runtime/vm/jit/irgen-basic.cpp),
  59. [irgen-arith.cpp](../../runtime/vm/jit/irgen-arith.cpp)). The `Translator`
  60. decides which HHIR instructions to emit based primarily on the types of the
  61. inputs to each bytecode.
  62. * `IRBuilder`: Defined in [ir-builder.h](../../runtime/vm/jit/ir-builder.h),
  63. this class is responsible for tracking state during symbolic execution and
  64. some very basic optimizations.
  65. * `IRUnit`: Defined in [ir-unit.h](../../runtime/vm/jit/ir-unit.h), this class
  66. is responsible for creating the runtime data structures that represent HHIR
  67. instructions, values, and blocks.
  68. * `Simplify`: Defined in [simplify.h](../../runtime/vm/jit/simplify.h),
  69. this class is responsible for performing very basic optimizations such as
  70. constant folding/propagation or anything else that only requires inspecting
  71. an instruction and its sources.
  72. ### Type System
  73. All values in HHIR have a type, represented by the `Type` class in
  74. [type.h](../../runtime/vm/jit/type.h). A `Type` may represent a primitive type
  75. or any arbitrary union of primitive types. Primitive types exist for
  76. PHP-visible types such as `Int`, `Obj`, and `Bool`, and runtime-internal types
  77. such as `FramePtr`, `Func`, and `Cls`. Primitive types also exist for PHP
  78. references and pointers to PHP values: for each primitive PHP type `T`,
  79. `BoxedT`, `PtrToT`, and `PtrToBoxedT` also exist. A number of types commonly
  80. thought of as primitives are actually unions: `Str` is the defined as
  81. `{StaticStr+CountedStr}` and `Arr` is defined as `{StaticArr+CountedArr}`. The
  82. `Type` class has static data members for easy construction of all primitive
  83. types and many common union types such as `Uncounted`, `Cell`, and `Gen`.
  84. In addition to arbitrary unions of primitive types, `Type` can also represent
  85. constant values and "specialized" types. A constant `Type` may represent the
  86. integer 5 or the string "Hello, world!", while a specialized type can represent
  87. an object of a specific class or an array of a specific kind.
  88. Since types represent sets of values, we define relations on types in terms of
  89. the sets of values they represent. Two types `S` and `T` are equal (`S == T`)
  90. if they represent equal sets of values. `S` is more refined than `T` (`S <= T`),
  91. or a subtype of `T`, if the set of values represented by `S` is a subset
  92. of the set of values represented by `T`. `S` and `T` are not related if their
  93. intersection is the empty set (also called `Bottom`).
  94. As previously mentioned, types in HHIR represent a mix of PHP-visible types and
  95. internal types. The following table describes types representing PHP
  96. values. Note that the types used here are more specific than what can be
  97. discriminated by user code (e.g., StaticStr and CountedStr both appear as type
  98. string at the PHP level).
  99. Type | HHVM representation
  100. ---------------|-------------------
  101. Uninit | `KindOfUninit`
  102. InitNull | `KindOfNull`
  103. Null | `{Uninit+InitNull}`
  104. Bool | `false=0`, `true=1` (8 bits at runtime)
  105. Int | `int64_t` (64-bit twos compliment binary integer)
  106. Dbl | `double` (IEEE 754 64-bit binary floating point)
  107. StaticStr | `StringData*` where `isStatic() == true`
  108. CountedStr | `StringData*` where `isStatic() == false`
  109. Str | `StringData*` `{CountedStr+StaticStr}`
  110. StaticArr | `ArrayData*` where `isStatic() == true`
  111. CountedArr | `ArrayData*` where `isStatic() == false`
  112. Arr | `ArrayData*` `{CountedArr+StaticArr}`
  113. UncountedInit | `TypedValue`: `{Null+Bool+Int+Dbl+StaticStr+StaticArr}`
  114. Uncounted | `TypedValue`: `{Uninit+Null+Bool+Int+Dbl+StaticStr+StaticArr}`
  115. Obj | `ObjectData*`
  116. Obj<Class> | `ObjectData*` of the specific type Class
  117. Counted | `{CountedStr+CountedArr+Obj+BoxedCell}`
  118. Cell | `{Null+Bool+Int+Dbl+Str+Arr+Obj}`
  119. A PHP reference is implemented as a container object (`RefData`) which contains
  120. one value. The contained value cannot be another PHP reference. For every type
  121. T in the table above, there is a corresponding type BoxedT, which is a pointer
  122. to a RefData struct containing a value of type T.
  123. Type | HHVM representation
  124. ---------------|--------------------
  125. BoxedInitNull | `RefData*` containing `InitNull`
  126. ... | Everything from the first table above can be boxed
  127. Finally, there is one top-level type representing all possible PHP values:
  128. Type | HHVM representation
  129. ---------------|--------------------
  130. Gen | `{Cell+BoxedCell}`
  131. The VM also manipulates values of various internal types, which are never
  132. visible at the PHP semantic level, and do not have any type relation with the
  133. above PHP-facing types.
  134. Type | HHVM representation
  135. ---------------|--------------------
  136. PtrToT | Exists for all T in `Gen`. Represents a `TypedValue*`
  137. Bottom | No value, `{}`. Subtype of every other type
  138. Top | Supertype of every other type
  139. Cls | `Class*`
  140. Func | `Func*`
  141. VarEnv | `VarEnv*`
  142. NamedEntity | `NamedEntity*`
  143. Cctx | A `Class*` with the lowest bit set (as stored in `ActRec::m_cls`)
  144. Ctx | `{Obj+Cctx}`
  145. RetAddr | Return address
  146. StkPtr | Pointer into VM execution stack
  147. FramePtr | Pointer to a frame on the VM execution stack
  148. TCA | Machine code address
  149. Nullptr | C++ `nullptr`
  150. There is also one special type which represents all the possible types that can
  151. be on the VM evaluation stack: all PHP-visible types plus the runtime-internal
  152. `Cls` type.
  153. Type | HHVM representation
  154. --------------|--------------------
  155. StkElem | `{Gen+Cls}`
  156. ### Values, Instructions, and Blocks
  157. An HHIR program is made up of `Blocks`, each containing one or more
  158. `IRInstructions`, each of which produces and consumes zero or more `SSATmp`
  159. values. These structures are defined in
  160. [block.h](../../runtime/vm/jit/block.h),
  161. [ir-instruction.h](../../runtime/vm/jit/ir-instruction.h), and
  162. [ssa-tmp.h](../../runtime/vm/jit/ssa-tmp.h), respectively.
  163. An `SSATmp` has a type, an SSA id, and a pointer to the `IRInstruction` that
  164. defined it. Every `SSATmp` is defined by exactly one `IRInstruction`, though
  165. one `IRInstruction` may define more than one `SSATmp`. Every instruction has an
  166. `Opcode`, indicating the operation it represents, and a `BCMarker`, which
  167. contains information about the HHBC instruction it is part of. Depending on the
  168. opcode of the instruction, it may also have one or more `SSATmp*` sources, one
  169. or more `SSATmp*` dests, one or more `Edge*`s to other `Blocks`, a `Type`
  170. parameter (known as a typeParam), and an `IRExtraData` struct to hold
  171. compile-time constants. `IRInstructions` are typically created with the
  172. `IRBuilder::gen()` method, which takes an `Opcode`, `BCMarker`, and then a
  173. variadic number of arguments representing the other properties of the
  174. instruction.
  175. A `Block` represents a basic block in a control flow graph. A pointer to one
  176. `Block` is stored in `IRUnit` as the entry point to the program; all other
  177. `Block`s must be reached by traversing the CFG. Certain instructions are "block
  178. end" instructions, meaning they must be the last instruction in their `Block`
  179. and they contain one or more `Edge`s to other `Block`s. `Jmp` is the simplest
  180. block end instruction; it represents an unconditional jump to a destination
  181. block. `CheckType` is an example of an instruction with two `Edge`s: "taken"
  182. and "next". It compares the runtime type of its source value to its typeParam,
  183. jumping to taken block if the type doesn't match, and jumping the next block if
  184. it does.
  185. While block end instructions may only exist at the end of a `Block`, there are
  186. two instructions that may only exist at the beginning of a `Block`: `DefLabel`
  187. and `BeginCatch`. `DefLabel` serves as a phi-node, joining values at control
  188. flow merge points. `BeginCatch` marks the beginning of a "catch block", which
  189. will be covered in more detail later.
  190. ### Control Flow
  191. HHIR can represent arbitrary control flow graphs, though most optimization
  192. passes do not currently support loops. In place of traditional phi-nodes, HHIR
  193. uses `Jmp` instructions that take sources and pass them to `DefLabel`
  194. instructions. Consider the following program that performs some numerical
  195. computation:
  196. ```
  197. B1:
  198. t1:Int = ...
  199. JmpZero t1:Int -> B3
  200. -> B2
  201. B2:
  202. t2:Int = AddInt t1:Int 5
  203. Jmp t2:Int -> B4
  204. B3:
  205. t3:Dbl = ConvIntToDbl t1:Int
  206. t4:Dbl = MulDbl t3:Dbl 3.14
  207. Jmp t4:Dbl -> B4
  208. B4:
  209. t5:{Int|Dbl} = DefLabel
  210. ...
  211. ```
  212. After control flow splits at the end of B1, B2 and B3 each do their own
  213. computation and then pass the result to the `DefLabel` at the join point,
  214. B4. This is equivalent to the following phi-node: `t5:{Int|Dbl} = phi(B2 ->
  215. t2:Int, B3 -> t4:Dbl)`
  216. ## Optimizations
  217. A number of basic optimizations are performed on each instruction by
  218. `IRBuilder` as it is generated and added to its `Block`: common sub-expression
  219. elimination, pre-optimization, and simplification. The CSE is fairly standard:
  220. the instruction and its sources are checked against a hash table to determine
  221. if the entire instruction can be replaced by an existing instruction performing
  222. the same computation. Pre-optimization performs simple optimizations based on
  223. tracked state in `IRBuilder`, such as replacing a `LdLoc` instruction with a
  224. use of an already known value for that local variable. Simplification comes
  225. last, and contains any optimizations that only require inspecting an
  226. instruction and its sources. This is primarily constant folding but also
  227. includes things like eliminating `CheckType` instructions that are known at
  228. compile-time to succeed. Both pre-optimization and simplification may return an
  229. already-defined value to use instead of the new instruction, or they may
  230. generate one or more different instructions to use in place of the original.
  231. Once the initial translation pass is complete, a series of more involved
  232. optimizations are run on the entire CFG. These are described in detail in
  233. [jit-optimizations.md](jit-optimizations.md).
  234. ## Machine Code Generation
  235. ### Register Allocation
  236. ### Code Generation
  237. #### x86-64
  238. #### ARM64