package wax-lib
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Libraries for Wax, a Rust-like syntax for WebAssembly
Install
dune-project
Dependency
Authors
Maintainers
Sources
wax-v0.2.0.tbz
sha256=4361e1324b7754a4c08ab5b505df32061f3ce0cea60443fd0d3699e0fa796b32
sha512=fcc756d2f160ba90a9aa1131f2ab22ed7f45466ccd658c21cf9df6868a6aab0cee7f404719d698a379958802f9820398f2fe0685ecc4dda018ca4f653294e39b
doc/src/wax-lib.wasm/hints.ml.html
Source file hints.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138type 'a hint = { value : 'a; loc : Wax_utils.Ast.location } type freq = int type 'idx t = { branch : bool hint option; freq : freq hint option; targets : ('idx * int) list hint option; } let none = { branch = None; freq = None; targets = None } (* Field by field rather than [t = none]: ['idx] is abstract here, so structural equality on a non-empty [targets] would reach into it. *) let is_empty { branch; freq; targets } = branch = None && freq = None && targets = None let branch loc value t = { t with branch = Some { value; loc } } let map_targets f t = match t.targets with | None -> { t with targets = None } | Some h -> { t with targets = Some { h with value = List.map (fun (x, pct) -> (f x, pct)) h.value }; } let freq loc value t = { t with freq = Some { value; loc } } let targets loc value t = { t with targets = Some { value; loc } } (*** Instruction frequency ***) (* The wire byte is an offset base-2 logarithm of the executions-per-call ratio: [f = max 1 (min 64 (floor (log2 r) + 32))], with [32] meaning once. The endpoints are saturating, so a ratio outside \[2^-31, 2^32\] pins to 1 or 64. *) let never_opt = 0 let always_opt = 127 let freq_of_ratio r = if r <= 0. then 1 else let l = int_of_float (Float.floor (Float.log2 r)) + 32 in max 1 (min 64 l) (* The ratio a byte stands for, when it is one the formula can produce. [None] for the two special values and for anything a hand-written binary put outside the range, which have no ratio and must round-trip through the raw payload. *) let ratio_of_freq b = if b >= 1 && b <= 64 then Some (Float.pow 2. (float_of_int (b - 32))) else None (*** Wire payloads ***) (* A [metadata.code.instr_freq] payload is a single byte. *) let freq_of_payload s = if String.length s = 1 then Ok (Char.code s.[0]) else Error "An instruction-frequency hint must be a single byte." let freq_payload b = String.make 1 (Char.chr (b land 0xff)) (* [metadata.code.call_targets] holds a run of LEB128 pairs, each a function index and a percentage. The text form spells the indices as names where it can; this decodes the raw-byte spelling, whose indices are numeric. *) let uleb_of_string s pos = let rec go pos shift acc = if pos >= String.length s then Error "A call-target hint ends mid-integer." else let b = Char.code s.[pos] in let acc = acc lor ((b land 0x7f) lsl shift) in if b land 0x80 = 0 then Ok (acc, pos + 1) else go (pos + 1) (shift + 7) acc in go pos 0 0 let call_targets_of_payload s = let rec go pos acc = if pos >= String.length s then Ok (List.rev acc) else match uleb_of_string s pos with | Error _ as e -> e | Ok (idx, pos) -> ( match uleb_of_string s pos with | Error _ as e -> e | Ok (pct, pos) -> go pos ((idx, pct) :: acc)) in go 0 [] let uleb_to_buffer b n = let rec go n = let byte = n land 0x7f and rest = n lsr 7 in if rest = 0 then Buffer.add_char b (Char.chr byte) else begin Buffer.add_char b (Char.chr (byte lor 0x80)); go rest end in go n let call_targets_payload l = let b = Buffer.create 16 in List.iter (fun (idx, pct) -> uleb_to_buffer b idx; uleb_to_buffer b pct) l; Buffer.contents b (*** Compilation priority ***) type priority = { compilation : int; optimization : int option } (* The proposal's prose gives 127 for "run once"; its own worked example instead renders the value as ["\01\1F"], i.e. 31. We follow the prose. The byte is only ever a spelling of this one value, so a binary carrying 31 round-trips as the plain number it is. *) let run_once = 127 (* A [metadata.code.compilation_priority] payload is a compilation priority, optionally followed by an optimization priority. The proposal's forward-compatibility rule says to read the leading values and ignore the rest, so trailing bytes are dropped rather than rejected. *) let priority_of_payload s = match uleb_of_string s 0 with | Error _ -> Error "A compilation-priority hint ends mid-integer." | Ok (compilation, pos) -> ( if pos >= String.length s then Ok { compilation; optimization = None } else match uleb_of_string s pos with | Error _ as e -> e | Ok (optimization, _) -> Ok { compilation; optimization = Some optimization }) let priority_payload { compilation; optimization } = let b = Buffer.create 4 in uleb_to_buffer b compilation; Option.iter (uleb_to_buffer b) optimization; Buffer.contents b
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>