_Z8as_charsIhEPKcPKT_:
   15|  10.8k|template <typename T> inline const char* as_chars(const T* data) {
   16|  10.8k|  return static_cast<const char*>(static_cast<const void*>(data));
   17|  10.8k|}

LLVMFuzzerTestOneInput:
   10|  10.8k|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   11|       |
   12|  10.8k|    auto begin = as_chars(Data);
   13|  10.8k|    auto end = begin + Size;
   14|       |
   15|  10.8k|    std::string str(begin, end);
   16|  10.8k|    simdjson::dom::parser parser;
   17|  10.8k|    simdjson::dom::element elem;
   18|  10.8k|    auto error = parser.parse(str).get(elem);
   19|  10.8k|    if (error) { return 0; }
  ------------------
  |  Branch (19:9): [True: 4.28k, False: 6.58k]
  ------------------
   20|       |
   21|  6.58k|    std::string minified=simdjson::minify(elem);
   22|  6.58k|    (void)minified;
   23|  6.58k|    return 0;
   24|  10.8k|}

_ZNK8simdjson3dom5array5beginEv:
   67|  8.24k|inline array::iterator array::begin() const noexcept {
   68|  8.24k|  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
  ------------------
  |  |  322|  8.24k|#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
  |  |  ------------------
  |  |  |  Branch (322:57): [Folded - Ignored]
  |  |  ------------------
  ------------------
   69|  8.24k|  return internal::tape_ref(tape.doc, tape.json_index + 1);
   70|  8.24k|}
_ZN8simdjson3dom5array8iteratorC2ERKNS_8internal8tape_refE:
  147|  16.4k|simdjson_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
_ZNK8simdjson3dom5array3endEv:
   71|  8.24k|inline array::iterator array::end() const noexcept {
   72|  8.24k|  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
  ------------------
  |  |  322|  8.24k|#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
  |  |  ------------------
  |  |  |  Branch (322:57): [Folded - Ignored]
  |  |  ------------------
  ------------------
   73|  8.24k|  return internal::tape_ref(tape.doc, tape.after_element() - 1);
   74|  8.24k|}
_ZNK8simdjson3dom5array8iteratorneERKS2_:
  160|  1.64M|inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
  161|  1.64M|  return tape.json_index != other.tape.json_index;
  162|  1.64M|}
_ZNK8simdjson3dom5array8iteratordeEv:
  148|  1.63M|inline element array::iterator::operator*() const noexcept {
  149|  1.63M|  return element(tape);
  150|  1.63M|}
_ZN8simdjson3dom5array8iteratorppEv:
  151|  1.63M|inline array::iterator& array::iterator::operator++() noexcept {
  152|  1.63M|  tape.json_index = tape.after_element();
  153|  1.63M|  return *this;
  154|  1.63M|}
_ZN8simdjson3dom5arrayC2ERKNS_8internal8tape_refE:
   66|  8.24k|simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}

_ZNK8simdjson3dom8document8capacityEv:
   24|  10.8k|inline size_t document::capacity() const noexcept {
   25|  10.8k|  return allocated_capacity;
   26|  10.8k|}
_ZN8simdjson3dom8document8allocateEm:
   29|  10.8k|inline error_code document::allocate(size_t capacity) noexcept {
   30|  10.8k|  if (capacity == 0) {
  ------------------
  |  Branch (30:7): [True: 0, False: 10.8k]
  ------------------
   31|      0|    string_buf.reset();
   32|      0|    tape.reset();
   33|      0|    allocated_capacity = 0;
   34|      0|    return SUCCESS;
   35|      0|  }
   36|       |
   37|       |  // a pathological input like "[[[[..." would generate capacity tape elements, so
   38|       |  // need a capacity of at least capacity + 1, but it is also possible to do
   39|       |  // worse with "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"
   40|       |  //where capacity + 1 tape elements are
   41|       |  // generated, see issue https://github.com/simdjson/simdjson/issues/345
   42|  10.8k|  size_t tape_capacity = SIMDJSON_ROUNDUP_N(capacity + 3, 64);
  ------------------
  |  |   47|  10.8k|#define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
  ------------------
   43|       |  // a document with only zero-length strings... could have capacity/3 string
   44|       |  // and we would need capacity/3 * 5 bytes on the string buffer
   45|  10.8k|  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * capacity / 3 + SIMDJSON_PADDING, 64);
  ------------------
  |  |   47|  10.8k|#define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
  ------------------
   46|  10.8k|  string_buf.reset( new (std::nothrow) uint8_t[string_capacity]);
   47|  10.8k|  tape.reset(new (std::nothrow) uint64_t[tape_capacity]);
   48|  10.8k|  if(!(string_buf && tape)) {
  ------------------
  |  Branch (48:8): [True: 10.8k, False: 0]
  |  Branch (48:22): [True: 10.8k, False: 0]
  ------------------
   49|      0|    allocated_capacity = 0;
   50|      0|    string_buf.reset();
   51|      0|    tape.reset();
   52|      0|    return MEMALLOC;
   53|      0|  }
   54|       |  // Technically the allocated_capacity might be larger than capacity
   55|       |  // so the next line is pessimistic.
   56|  10.8k|  allocated_capacity = capacity;
   57|  10.8k|  return SUCCESS;
   58|  10.8k|}
_ZNK8simdjson3dom8document4rootEv:
   20|  6.58k|inline element document::root() const noexcept {
   21|  6.58k|  return element(internal::tape_ref(this, 1));
   22|  6.58k|}

_ZN8simdjson3dom8documentC2Ev:
   23|  10.8k|  document() noexcept = default;
_ZN8simdjson3dom8documentD2Ev:
   24|  10.8k|  ~document() noexcept = default;

_ZN8simdjson3dom7elementC2Ev:
  197|  15.1k|simdjson_inline element::element() noexcept : tape{} {}
_ZN8simdjson15simdjson_resultINS_3dom7elementEEC2ENS_10error_codeE:
   27|  4.28k|    : internal::simdjson_result_base<dom::element>(error) {}
_ZN8simdjson3dom7elementC2ERKNS_8internal8tape_refE:
  198|  1.79M|simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
_ZN8simdjson15simdjson_resultINS_3dom7elementEEC2EOS2_:
   25|  6.58k|    : internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
_ZNK8simdjson15simdjson_resultINS_3dom7elementEE3getIS2_EENS_10error_codeERT_:
   43|  10.8k|simdjson_warn_unused simdjson_inline error_code simdjson_result<dom::element>::get(T &value) const noexcept {
   44|  10.8k|  if (error()) { return error(); }
  ------------------
  |  Branch (44:7): [True: 4.28k, False: 6.58k]
  ------------------
   45|  6.58k|  return first.get<T>(value);
   46|  10.8k|}
_ZNK8simdjson3dom7element3getIS1_EENS_10error_codeERT_:
  320|  6.58k|simdjson_warn_unused simdjson_inline error_code element::get<element>(element &value) const noexcept {
  321|  6.58k|  value = element(tape);
  322|  6.58k|  return SUCCESS;
  323|  6.58k|}

_ZNK8simdjson3dom6object5beginEv:
   76|  5.58k|inline object::iterator object::begin() const noexcept {
   77|  5.58k|  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
  ------------------
  |  |  322|  5.58k|#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
  |  |  ------------------
  |  |  |  Branch (322:57): [Folded - Ignored]
  |  |  ------------------
  ------------------
   78|  5.58k|  return internal::tape_ref(tape.doc, tape.json_index + 1);
   79|  5.58k|}
_ZN8simdjson3dom6object8iteratorC2ERKNS_8internal8tape_refE:
  175|  11.1k|simdjson_inline object::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
_ZNK8simdjson3dom6object3endEv:
   80|  5.58k|inline object::iterator object::end() const noexcept {
   81|  5.58k|  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
  ------------------
  |  |  322|  5.58k|#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
  |  |  ------------------
  |  |  |  Branch (322:57): [Folded - Ignored]
  |  |  ------------------
  ------------------
   82|  5.58k|  return internal::tape_ref(tape.doc, tape.after_element() - 1);
   83|  5.58k|}
_ZNK8simdjson3dom6object8iteratorneERKS2_:
  179|   153k|inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
  180|   153k|  return tape.json_index != other.tape.json_index;
  181|   153k|}
_ZNK8simdjson3dom6object8iteratordeEv:
  176|   147k|inline const key_value_pair object::iterator::operator*() const noexcept {
  177|   147k|  return key_value_pair(key(), value());
  178|   147k|}
_ZNK8simdjson3dom6object8iterator3keyEv:
  207|   147k|inline std::string_view object::iterator::key() const noexcept {
  208|   147k|  return tape.get_string_view();
  209|   147k|}
_ZNK8simdjson3dom6object8iterator5valueEv:
  216|   147k|inline element object::iterator::value() const noexcept {
  217|   147k|  return element(internal::tape_ref(tape.doc, tape.json_index + 1));
  218|   147k|}
_ZN8simdjson3dom14key_value_pairC2ENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEENS0_7elementE:
  260|   147k|  key(_key), value(_value) {}
_ZN8simdjson3dom6object8iteratorppEv:
  197|   147k|inline object::iterator& object::iterator::operator++() noexcept {
  198|   147k|  tape.json_index++;
  199|   147k|  tape.json_index = tape.after_element();
  200|   147k|  return *this;
  201|   147k|}
_ZN8simdjson3dom6objectC2ERKNS_8internal8tape_refE:
   75|  5.58k|simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }

_ZN8simdjson3dom6parserC2Em:
   24|  10.8k|  : _max_capacity{max_capacity},
   25|  10.8k|    loaded_bytes(nullptr) {
   26|  10.8k|}
_ZNR8simdjson3dom6parser5parseERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  160|  10.8k|simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & noexcept {
  161|  10.8k|  return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
  162|  10.8k|}
_ZNR8simdjson3dom6parser5parseEPKcmb:
  157|  10.8k|simdjson_inline simdjson_result<element> parser::parse(const char *buf, size_t len, bool realloc_if_needed) & noexcept {
  158|  10.8k|  return parse(reinterpret_cast<const uint8_t *>(buf), len, realloc_if_needed);
  159|  10.8k|}
_ZNR8simdjson3dom6parser5parseEPKhmb:
  153|  10.8k|inline simdjson_result<element> parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
  154|  10.8k|  return parse_into_document(doc, buf, len, realloc_if_needed);
  155|  10.8k|}
_ZNR8simdjson3dom6parser19parse_into_documentERNS0_8documentEPKhmb:
  113|  10.8k|inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
  114|       |  // Important: we need to ensure that document has enough capacity.
  115|       |  // Important: It is possible that provided_doc is actually the internal 'doc' within the parser!!!
  116|  10.8k|  error_code _error = ensure_capacity(provided_doc, len);
  117|  10.8k|  if (_error) { return _error; }
  ------------------
  |  Branch (117:7): [True: 0, False: 10.8k]
  ------------------
  118|  10.8k|  if (realloc_if_needed) {
  ------------------
  |  Branch (118:7): [True: 10.8k, False: 0]
  ------------------
  119|       |    // Make sure we have enough capacity to copy len bytes
  120|  10.8k|    if (!loaded_bytes || _loaded_bytes_capacity < len) {
  ------------------
  |  Branch (120:9): [True: 10.8k, False: 0]
  |  Branch (120:26): [True: 0, False: 0]
  ------------------
  121|  10.8k|      loaded_bytes.reset( internal::allocate_padded_buffer(len) );
  122|  10.8k|      if (!loaded_bytes) {
  ------------------
  |  Branch (122:11): [True: 9, False: 10.8k]
  ------------------
  123|      9|        return MEMALLOC;
  124|      9|      }
  125|  10.8k|      _loaded_bytes_capacity = len;
  126|  10.8k|    }
  127|  10.8k|    std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
  128|  10.8k|    buf = reinterpret_cast<const uint8_t*>(loaded_bytes.get());
  129|  10.8k|  }
  130|       |
  131|  10.8k|  if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  Branch (131:6): [True: 10.7k, False: 77]
  |  Branch (131:20): [True: 15, False: 10.7k]
  ------------------
  132|     15|    buf += 3;
  133|     15|    len -= 3;
  134|     15|  }
  135|  10.8k|  _error = implementation->parse(buf, len, provided_doc);
  136|       |
  137|  10.8k|  if (_error) { return _error; }
  ------------------
  |  Branch (137:7): [True: 4.27k, False: 6.58k]
  ------------------
  138|       |
  139|  6.58k|  return provided_doc.root();
  140|  10.8k|}
_ZN8simdjson3dom6parser15ensure_capacityERNS0_8documentEm:
  225|  10.8k|inline error_code parser::ensure_capacity(document& target_document, size_t desired_capacity) noexcept {
  226|       |  // 1. It is wasteful to allocate a document and a parser for documents spanning less than MINIMAL_DOCUMENT_CAPACITY bytes.
  227|       |  // 2. If we allow desired_capacity = 0 then it is possible to exit this function with implementation == nullptr.
  228|  10.8k|  if(desired_capacity < MINIMAL_DOCUMENT_CAPACITY) { desired_capacity = MINIMAL_DOCUMENT_CAPACITY; }
  ------------------
  |  Branch (228:6): [True: 7.09k, False: 3.77k]
  ------------------
  229|       |  // If we don't have enough capacity, (try to) automatically bump it.
  230|       |  // If the document needs allocation, do it too.
  231|       |  // Both in one if statement to minimize unlikely branching.
  232|       |  //
  233|       |  // Note: we must make sure that this function is called if capacity() == 0. We do so because we
  234|       |  // ensure that desired_capacity > 0.
  235|  10.8k|  if (simdjson_unlikely(capacity() < desired_capacity || target_document.capacity() < desired_capacity)) {
  ------------------
  |  |  106|  10.8k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 10.8k, False: 0]
  |  |  |  Branch (106:52): [True: 10.8k, False: 0]
  |  |  |  Branch (106:52): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  236|  10.8k|    if (desired_capacity > max_capacity()) {
  ------------------
  |  Branch (236:9): [True: 0, False: 10.8k]
  ------------------
  237|      0|      return error = CAPACITY;
  238|      0|    }
  239|  10.8k|    error_code err1 = target_document.capacity() < desired_capacity ? target_document.allocate(desired_capacity) : SUCCESS;
  ------------------
  |  Branch (239:23): [True: 10.8k, False: 0]
  ------------------
  240|  10.8k|    error_code err2 = capacity() < desired_capacity ? allocate(desired_capacity, max_depth()) : SUCCESS;
  ------------------
  |  Branch (240:23): [True: 10.8k, False: 0]
  ------------------
  241|  10.8k|    if(err1 != SUCCESS) { return error = err1; }
  ------------------
  |  Branch (241:8): [True: 0, False: 10.8k]
  ------------------
  242|  10.8k|    if(err2 != SUCCESS) { return error = err2; }
  ------------------
  |  Branch (242:8): [True: 0, False: 10.8k]
  ------------------
  243|  10.8k|  }
  244|  10.8k|  return SUCCESS;
  245|  10.8k|}
_ZNK8simdjson3dom6parser8capacityEv:
  188|  21.7k|simdjson_inline size_t parser::capacity() const noexcept {
  189|  21.7k|  return implementation ? implementation->capacity() : 0;
  ------------------
  |  Branch (189:10): [True: 0, False: 21.7k]
  ------------------
  190|  21.7k|}
_ZNK8simdjson3dom6parser12max_capacityEv:
  191|  10.8k|simdjson_inline size_t parser::max_capacity() const noexcept {
  192|  10.8k|  return _max_capacity;
  193|  10.8k|}
_ZN8simdjson3dom6parser8allocateEmm:
  199|  10.8k|inline error_code parser::allocate(size_t capacity, size_t max_depth) noexcept {
  200|       |  //
  201|       |  // Reallocate implementation if needed
  202|       |  //
  203|  10.8k|  error_code err;
  204|  10.8k|  if (implementation) {
  ------------------
  |  Branch (204:7): [True: 0, False: 10.8k]
  ------------------
  205|      0|    err = implementation->allocate(capacity, max_depth);
  206|  10.8k|  } else {
  207|  10.8k|    err = simdjson::get_active_implementation()->create_dom_parser_implementation(capacity, max_depth, implementation);
  208|  10.8k|  }
  209|  10.8k|  if (err) { return err; }
  ------------------
  |  Branch (209:7): [True: 0, False: 10.8k]
  ------------------
  210|  10.8k|  return SUCCESS;
  211|  10.8k|}
_ZNK8simdjson3dom6parser9max_depthEv:
  194|  10.8k|simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept {
  195|  10.8k|  return implementation ? implementation->max_depth() : DEFAULT_MAX_DEPTH;
  ------------------
  |  Branch (195:10): [True: 0, False: 10.8k]
  ------------------
  196|  10.8k|}

_ZN8simdjson3dom6parserD2Ev:
   60|  10.8k|  ~parser()=default;

_ZN8simdjson8internal14string_builderINS0_14mini_formatterEE6appendENS_3dom7elementE:
  345|  1.79M|inline void string_builder<serializer>::append(simdjson::dom::element value) {
  346|       |  // using tape_type = simdjson::internal::tape_type;
  347|  1.79M|  size_t depth = 0;
  348|  1.79M|  constexpr size_t MAX_DEPTH = 16;
  349|  1.79M|  bool is_object[MAX_DEPTH];
  350|  1.79M|  is_object[0] = false;
  351|  1.79M|  bool after_value = false;
  352|       |
  353|  1.79M|  internal::tape_ref iter(value.tape);
  354|  5.18M|  do {
  355|       |    // print commas after each value
  356|  5.18M|    if (after_value) {
  ------------------
  |  Branch (356:9): [True: 3.33M, False: 1.85M]
  ------------------
  357|  3.33M|      format.comma();
  358|  3.33M|      format.print_newline();
  359|  3.33M|    }
  360|       |
  361|  5.18M|    format.print_indents(depth);
  362|       |
  363|       |    // If we are in an object, print the next key and :, and skip to the next
  364|       |    // value.
  365|  5.18M|    if (is_object[depth]) {
  ------------------
  |  Branch (365:9): [True: 92.0k, False: 5.09M]
  ------------------
  366|  92.0k|      format.key(iter.get_string_view());
  367|  92.0k|      format.print_space();
  368|  92.0k|      iter.json_index++;
  369|  92.0k|    }
  370|  5.18M|    switch (iter.tape_ref_type()) {
  ------------------
  |  Branch (370:13): [True: 0, False: 5.18M]
  ------------------
  371|       |
  372|       |    // Arrays
  373|  70.6k|    case tape_type::START_ARRAY: {
  ------------------
  |  Branch (373:5): [True: 70.6k, False: 5.11M]
  ------------------
  374|       |      // If we're too deep, we need to recurse to go deeper.
  375|  70.6k|      depth++;
  376|  70.6k|      if (simdjson_unlikely(depth >= MAX_DEPTH)) {
  ------------------
  |  |  106|  70.6k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 8.24k, False: 62.4k]
  |  |  ------------------
  ------------------
  377|  8.24k|        append(simdjson::dom::array(iter));
  378|  8.24k|        iter.json_index = iter.matching_brace_index() - 1; // Jump to the ]
  379|  8.24k|        depth--;
  380|  8.24k|        break;
  381|  8.24k|      }
  382|       |
  383|       |      // Output start [
  384|  62.4k|      format.start_array();
  385|  62.4k|      iter.json_index++;
  386|       |
  387|       |      // Handle empty [] (we don't want to come back around and print commas)
  388|  62.4k|      if (iter.tape_ref_type() == tape_type::END_ARRAY) {
  ------------------
  |  Branch (388:11): [True: 5.70k, False: 56.7k]
  ------------------
  389|  5.70k|        format.end_array();
  390|  5.70k|        depth--;
  391|  5.70k|        break;
  392|  5.70k|      }
  393|       |
  394|  56.7k|      is_object[depth] = false;
  395|  56.7k|      after_value = false;
  396|  56.7k|      format.print_newline();
  397|  56.7k|      continue;
  398|  62.4k|    }
  399|       |
  400|       |    // Objects
  401|  12.1k|    case tape_type::START_OBJECT: {
  ------------------
  |  Branch (401:5): [True: 12.1k, False: 5.17M]
  ------------------
  402|       |      // If we're too deep, we need to recurse to go deeper.
  403|  12.1k|      depth++;
  404|  12.1k|      if (simdjson_unlikely(depth >= MAX_DEPTH)) {
  ------------------
  |  |  106|  12.1k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 5.58k, False: 6.54k]
  |  |  ------------------
  ------------------
  405|  5.58k|        append(simdjson::dom::object(iter));
  406|  5.58k|        iter.json_index = iter.matching_brace_index() - 1; // Jump to the }
  407|  5.58k|        depth--;
  408|  5.58k|        break;
  409|  5.58k|      }
  410|       |
  411|       |      // Output start {
  412|  6.54k|      format.start_object();
  413|  6.54k|      iter.json_index++;
  414|       |
  415|       |      // Handle empty {} (we don't want to come back around and print commas)
  416|  6.54k|      if (iter.tape_ref_type() == tape_type::END_OBJECT) {
  ------------------
  |  Branch (416:11): [True: 2.13k, False: 4.41k]
  ------------------
  417|  2.13k|        format.end_object();
  418|  2.13k|        depth--;
  419|  2.13k|        break;
  420|  2.13k|      }
  421|       |
  422|  4.41k|      is_object[depth] = true;
  423|  4.41k|      after_value = false;
  424|  4.41k|      format.print_newline();
  425|  4.41k|      continue;
  426|  6.54k|    }
  427|       |
  428|       |    // Scalars
  429|  3.93k|    case tape_type::STRING:
  ------------------
  |  Branch (429:5): [True: 3.93k, False: 5.18M]
  ------------------
  430|  3.93k|      format.string(iter.get_string_view());
  431|  3.93k|      break;
  432|  2.32M|    case tape_type::INT64:
  ------------------
  |  Branch (432:5): [True: 2.32M, False: 2.86M]
  ------------------
  433|  2.32M|      format.number(iter.next_tape_value<int64_t>());
  434|  2.32M|      iter.json_index++; // numbers take up 2 spots, so we need to increment
  435|       |                         // extra
  436|  2.32M|      break;
  437|  1.88k|    case tape_type::UINT64:
  ------------------
  |  Branch (437:5): [True: 1.88k, False: 5.18M]
  ------------------
  438|  1.88k|      format.number(iter.next_tape_value<uint64_t>());
  439|  1.88k|      iter.json_index++; // numbers take up 2 spots, so we need to increment
  440|       |                         // extra
  441|  1.88k|      break;
  442|  2.77M|    case tape_type::DOUBLE:
  ------------------
  |  Branch (442:5): [True: 2.77M, False: 2.41M]
  ------------------
  443|  2.77M|      format.number(iter.next_tape_value<double>());
  444|  2.77M|      iter.json_index++; // numbers take up 2 spots, so we need to increment
  445|       |                         // extra
  446|  2.77M|      break;
  447|    287|    case tape_type::TRUE_VALUE:
  ------------------
  |  Branch (447:5): [True: 287, False: 5.18M]
  ------------------
  448|    287|      format.true_atom();
  449|    287|      break;
  450|    262|    case tape_type::FALSE_VALUE:
  ------------------
  |  Branch (450:5): [True: 262, False: 5.18M]
  ------------------
  451|    262|      format.false_atom();
  452|    262|      break;
  453|    261|    case tape_type::NULL_VALUE:
  ------------------
  |  Branch (453:5): [True: 261, False: 5.18M]
  ------------------
  454|    261|      format.null_atom();
  455|    261|      break;
  456|       |
  457|       |    // These are impossible
  458|      0|    case tape_type::END_ARRAY:
  ------------------
  |  Branch (458:5): [True: 0, False: 5.18M]
  ------------------
  459|      0|    case tape_type::END_OBJECT:
  ------------------
  |  Branch (459:5): [True: 0, False: 5.18M]
  ------------------
  460|      0|    case tape_type::ROOT:
  ------------------
  |  Branch (460:5): [True: 0, False: 5.18M]
  ------------------
  461|      0|      SIMDJSON_UNREACHABLE();
  ------------------
  |  |  198|      0|#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
  ------------------
  462|  5.18M|    }
  463|  5.12M|    iter.json_index++;
  464|  5.12M|    after_value = true;
  465|       |
  466|       |    // Handle multiple ends in a row
  467|  5.18M|    while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
  ------------------
  |  Branch (467:12): [True: 3.39M, False: 1.79M]
  |  Branch (467:27): [True: 56.7k, False: 3.33M]
  ------------------
  468|  3.39M|                          iter.tape_ref_type() == tape_type::END_OBJECT)) {
  ------------------
  |  Branch (468:27): [True: 4.41k, False: 3.33M]
  ------------------
  469|  61.1k|      format.print_newline();
  470|  61.1k|      depth--;
  471|  61.1k|      format.print_indents(depth);
  472|  61.1k|      if (iter.tape_ref_type() == tape_type::END_ARRAY) {
  ------------------
  |  Branch (472:11): [True: 56.7k, False: 4.41k]
  ------------------
  473|  56.7k|        format.end_array();
  474|  56.7k|      } else {
  475|  4.41k|        format.end_object();
  476|  4.41k|      }
  477|  61.1k|      iter.json_index++;
  478|  61.1k|    }
  479|       |
  480|       |    // Stop when we're at depth 0
  481|  5.18M|  } while (depth != 0);
  ------------------
  |  Branch (481:12): [True: 3.39M, False: 1.79M]
  ------------------
  482|       |
  483|  1.79M|  format.print_newline();
  484|  1.79M|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE5commaEv:
  190|  5.10M|simdjson_inline void base_formatter<formatter>::comma() { one_char(','); }
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE8one_charEc:
  211|  8.98M|simdjson_inline void base_formatter<formatter>::one_char(char c) { buffer.push_back(c); }
_ZN8simdjson8internal14mini_formatter13print_newlineEv:
  310|  5.24M|simdjson_inline void mini_formatter::print_newline() {
  311|  5.24M|    return;
  312|  5.24M|}
_ZN8simdjson8internal14mini_formatter13print_indentsEm:
  314|  5.24M|simdjson_inline void mini_formatter::print_indents(size_t depth) {
  315|  5.24M|    (void)depth;
  316|  5.24M|    return;
  317|  5.24M|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE3keyENSt3__117basic_string_viewIcNS4_11char_traitsIcEEEE:
  214|   239k|simdjson_inline void base_formatter<formatter>::key(std::string_view unescaped) {
  215|   239k|  string(unescaped);
  216|   239k|  one_char(':');
  217|   239k|}
_ZN8simdjson8internal14mini_formatter11print_spaceEv:
  319|  92.0k|simdjson_inline void mini_formatter::print_space() {
  320|  92.0k|    return;
  321|  92.0k|}
_ZN8simdjson8internal14string_builderINS0_14mini_formatterEE6appendENS_3dom5arrayE:
  502|  8.24k|inline void string_builder<serializer>::append(simdjson::dom::array value) {
  503|  8.24k|  format.start_array();
  504|  8.24k|  auto iter = value.begin();
  505|  8.24k|  auto end = value.end();
  506|  8.24k|  if (iter != end) {
  ------------------
  |  Branch (506:7): [True: 6.65k, False: 1.59k]
  ------------------
  507|  6.65k|    append(*iter);
  508|  1.63M|    for (++iter; iter != end; ++iter) {
  ------------------
  |  Branch (508:18): [True: 1.63M, False: 6.65k]
  ------------------
  509|  1.63M|      format.comma();
  510|  1.63M|      append(*iter);
  511|  1.63M|    }
  512|  6.65k|  }
  513|  8.24k|  format.end_array();
  514|  8.24k|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE11start_arrayEv:
  177|  70.6k|simdjson_inline void base_formatter<formatter>::start_array() { one_char('['); }
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE9end_arrayEv:
  181|  70.6k|simdjson_inline void base_formatter<formatter>::end_array() { one_char(']'); }
_ZN8simdjson8internal14string_builderINS0_14mini_formatterEE6appendENS_3dom6objectE:
  487|  5.58k|inline void string_builder<serializer>::append(simdjson::dom::object value) {
  488|  5.58k|  format.start_object();
  489|  5.58k|  auto pair = value.begin();
  490|  5.58k|  auto end = value.end();
  491|  5.58k|  if (pair != end) {
  ------------------
  |  Branch (491:7): [True: 5.07k, False: 508]
  ------------------
  492|  5.07k|    append(*pair);
  493|   147k|    for (++pair; pair != end; ++pair) {
  ------------------
  |  Branch (493:18): [True: 142k, False: 5.07k]
  ------------------
  494|   142k|      format.comma();
  495|   142k|      append(*pair);
  496|   142k|    }
  497|  5.07k|  }
  498|  5.58k|  format.end_object();
  499|  5.58k|}
_ZN8simdjson8internal14string_builderINS0_14mini_formatterEE6appendENS_3dom14key_value_pairE:
  517|   147k|simdjson_inline void string_builder<serializer>::append(simdjson::dom::key_value_pair kv) {
  518|   147k|  format.key(kv.key);
  519|   147k|  append(kv.value);
  520|   147k|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE12start_objectEv:
  184|  12.1k|simdjson_inline void base_formatter<formatter>::start_object() { one_char('{'); }
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE10end_objectEv:
  187|  12.1k|simdjson_inline void base_formatter<formatter>::end_object() { one_char('}'); }
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE6stringENSt3__117basic_string_viewIcNS4_11char_traitsIcEEEE:
  220|   243k|simdjson_inline void base_formatter<formatter>::string(std::string_view unescaped) {
  221|   243k|  one_char('\"');
  222|   243k|  size_t i = 0;
  223|       |  // Fast path for the case where we have no control character, no ", and no backslash.
  224|       |  // This should include most keys.
  225|       |  //
  226|       |  // We would like to use 'bool' but some compilers take offense to bitwise operation
  227|       |  // with bool types.
  228|   243k|  constexpr static char needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  229|   243k|    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
  230|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  231|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
  232|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  233|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  234|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  235|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  236|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  237|   243k|    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  238|  3.25M|  for(;i + 8 <= unescaped.length(); i += 8) {
  ------------------
  |  Branch (238:8): [True: 3.01M, False: 241k]
  ------------------
  239|       |    // Poor's man vectorization. This could get much faster if we used SIMD.
  240|       |    //
  241|       |    // It is not the case that replacing '|' with '||' would be neutral performance-wise.
  242|  3.01M|    if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
  ------------------
  |  Branch (242:8): [True: 2.31k, False: 3.01M]
  ------------------
  243|  3.01M|      | needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
  244|  3.01M|      | needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
  245|  3.01M|      | needs_escaping[uint8_t(unescaped[i+6])] | needs_escaping[uint8_t(unescaped[i+7])]
  246|  3.01M|      ) { break; }
  247|  3.01M|  }
  248|   284k|  for(;i < unescaped.length(); i++) {
  ------------------
  |  Branch (248:8): [True: 46.6k, False: 238k]
  ------------------
  249|  46.6k|    if(needs_escaping[uint8_t(unescaped[i])]) { break; }
  ------------------
  |  Branch (249:8): [True: 5.40k, False: 41.2k]
  ------------------
  250|  46.6k|  }
  251|       |  // The following is also possible and omits a 256-byte table, but it is slower:
  252|       |  // for (; (i < unescaped.length()) && (uint8_t(unescaped[i]) > 0x1F)
  253|       |  //      && (unescaped[i] != '\"') && (unescaped[i] != '\\'); i++) {}
  254|       |
  255|       |  // At least for long strings, the following should be fast. We could
  256|       |  // do better by integrating the checks and the insertion.
  257|   243k|  buffer.insert(buffer.end(), unescaped.data(), unescaped.data() + i);
  258|       |  // We caught a control character if we enter this loop (slow).
  259|       |  // Note that we are do not restart from the beginning, but rather we continue
  260|       |  // from the point where we encountered something that requires escaping.
  261|  3.26M|  for (; i < unescaped.length(); i++) {
  ------------------
  |  Branch (261:10): [True: 3.01M, False: 243k]
  ------------------
  262|  3.01M|    switch (unescaped[i]) {
  263|  3.46k|    case '\"':
  ------------------
  |  Branch (263:5): [True: 3.46k, False: 3.01M]
  ------------------
  264|  3.46k|      {
  265|  3.46k|        const char * s = "\\\"";
  266|  3.46k|        buffer.insert(buffer.end(), s, s + 2);
  267|  3.46k|      }
  268|  3.46k|      break;
  269|  24.4k|    case '\\':
  ------------------
  |  Branch (269:5): [True: 24.4k, False: 2.99M]
  ------------------
  270|  24.4k|      {
  271|  24.4k|        const char * s = "\\\\";
  272|  24.4k|        buffer.insert(buffer.end(), s, s + 2);
  273|  24.4k|      }
  274|  24.4k|      break;
  275|  2.99M|    default:
  ------------------
  |  Branch (275:5): [True: 2.99M, False: 27.8k]
  ------------------
  276|  2.99M|      if (uint8_t(unescaped[i]) <= 0x1F) {
  ------------------
  |  Branch (276:11): [True: 4.15k, False: 2.98M]
  ------------------
  277|       |        // If packed, this uses 8 * 32 bytes.
  278|       |        // Note that we expect most compilers to embed this code in the data
  279|       |        // section.
  280|  4.15k|        constexpr static escape_sequence escaped[32] = {
  281|  4.15k|          {6, "\\u0000"}, {6, "\\u0001"}, {6, "\\u0002"}, {6, "\\u0003"},
  282|  4.15k|          {6, "\\u0004"}, {6, "\\u0005"}, {6, "\\u0006"}, {6, "\\u0007"},
  283|  4.15k|          {2, "\\b"},     {2, "\\t"},     {2, "\\n"},     {6, "\\u000b"},
  284|  4.15k|          {2, "\\f"},     {2, "\\r"},     {6, "\\u000e"}, {6, "\\u000f"},
  285|  4.15k|          {6, "\\u0010"}, {6, "\\u0011"}, {6, "\\u0012"}, {6, "\\u0013"},
  286|  4.15k|          {6, "\\u0014"}, {6, "\\u0015"}, {6, "\\u0016"}, {6, "\\u0017"},
  287|  4.15k|          {6, "\\u0018"}, {6, "\\u0019"}, {6, "\\u001a"}, {6, "\\u001b"},
  288|  4.15k|          {6, "\\u001c"}, {6, "\\u001d"}, {6, "\\u001e"}, {6, "\\u001f"}};
  289|  4.15k|        auto u = escaped[uint8_t(unescaped[i])];
  290|  4.15k|        buffer.insert(buffer.end(), u.string, u.string + u.length);
  291|  2.98M|      } else {
  292|  2.98M|        one_char(unescaped[i]);
  293|  2.98M|      }
  294|  3.01M|    } // switch
  295|  3.01M|  }   // for
  296|   243k|  one_char('\"');
  297|   243k|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE6numberEl:
  160|  2.32M|simdjson_inline void base_formatter<formatter>::number(int64_t x) {
  161|  2.32M|  char number_buffer[24];
  162|  2.32M|  char *newp = fast_itoa(number_buffer, x);
  163|  2.32M|  buffer.insert(buffer.end(), number_buffer, newp);
  164|  2.32M|}
fuzz_minify.cpp:_ZN8simdjson12_GLOBAL__N_19fast_itoaEPcl:
   84|  2.32M|static char *fast_itoa(char *output, int64_t value) noexcept {
   85|       |  // This is a standard implementation of itoa.
   86|  2.32M|  char buffer[20];
   87|  2.32M|  uint64_t value_positive;
   88|       |  // In general, negating a signed integer is unsafe.
   89|  2.32M|  if(value < 0) {
  ------------------
  |  Branch (89:6): [True: 3.92k, False: 2.31M]
  ------------------
   90|  3.92k|    *output++ = '-';
   91|       |    // Doing value_positive = -value; while avoiding
   92|       |    // undefined behavior warnings.
   93|       |    // It assumes two complement's which is universal at this
   94|       |    // point in time.
   95|  3.92k|    std::memcpy(&value_positive, &value, sizeof(value));
   96|  3.92k|    value_positive = (~value_positive) + 1; // this is a negation
   97|  2.31M|  } else {
   98|  2.31M|    value_positive = value;
   99|  2.31M|  }
  100|       |  // We work solely with value_positive. It *might* be easier
  101|       |  // for an optimizing compiler to deal with an unsigned variable
  102|       |  // as far as performance goes.
  103|  2.32M|  const char *const end_buffer = buffer + 20;
  104|  2.32M|  char *write_pointer = buffer + 19;
  105|       |  // A faster approach is possible if we expect large integers:
  106|       |  // unroll the loop (work in 100s, 1000s) and use some kind of
  107|       |  // memoization.
  108|  2.53M|  while(value_positive >= 10) {
  ------------------
  |  Branch (108:9): [True: 208k, False: 2.32M]
  ------------------
  109|   208k|    *write_pointer-- = char('0' + (value_positive % 10));
  110|   208k|    value_positive /= 10;
  111|   208k|  }
  112|  2.32M|  *write_pointer = char('0' + value_positive);
  113|  2.32M|  size_t len = end_buffer - write_pointer;
  114|  2.32M|  std::memcpy(output, write_pointer, len);
  115|  2.32M|  return output + len;
  116|  2.32M|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE6numberEm:
  153|  1.88k|simdjson_inline void base_formatter<formatter>::number(uint64_t x) {
  154|  1.88k|  char number_buffer[24];
  155|  1.88k|  char *newp = fast_itoa(number_buffer, x);
  156|  1.88k|  buffer.insert(buffer.end(), number_buffer, newp);
  157|  1.88k|}
fuzz_minify.cpp:_ZN8simdjson12_GLOBAL__N_19fast_itoaEPcm:
  126|  1.88k|static char *fast_itoa(char *output, uint64_t value) noexcept {
  127|       |  // This is a standard implementation of itoa.
  128|  1.88k|  char buffer[20];
  129|  1.88k|  const char *const end_buffer = buffer + 20;
  130|  1.88k|  char *write_pointer = buffer + 19;
  131|       |  // A faster approach is possible if we expect large integers:
  132|       |  // unroll the loop (work in 100s, 1000s) and use some kind of
  133|       |  // memoization.
  134|  36.7k|  while(value >= 10) {
  ------------------
  |  Branch (134:9): [True: 34.8k, False: 1.88k]
  ------------------
  135|  34.8k|    *write_pointer-- = char('0' + (value % 10));
  136|  34.8k|    value /= 10;
  137|  34.8k|  };
  138|  1.88k|  *write_pointer = char('0' + value);
  139|  1.88k|  size_t len = end_buffer - write_pointer;
  140|  1.88k|  std::memcpy(output, write_pointer, len);
  141|  1.88k|  return output + len;
  142|  1.88k|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE6numberEd:
  167|  2.77M|simdjson_inline void base_formatter<formatter>::number(double x) {
  168|  2.77M|  char number_buffer[24];
  169|       |  // Currently, passing the nullptr to the second argument is
  170|       |  // safe because our implementation does not check the second
  171|       |  // argument.
  172|  2.77M|  char *newp = internal::to_chars(number_buffer, nullptr, x);
  173|  2.77M|  buffer.insert(buffer.end(), number_buffer, newp);
  174|  2.77M|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE9true_atomEv:
  193|    287|simdjson_inline void base_formatter<formatter>::true_atom() {
  194|    287|  const char * s = "true";
  195|    287|  buffer.insert(buffer.end(), s, s + 4);
  196|    287|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE10false_atomEv:
  199|    262|simdjson_inline void base_formatter<formatter>::false_atom() {
  200|    262|  const char * s = "false";
  201|    262|  buffer.insert(buffer.end(), s, s + 5);
  202|    262|}
_ZN8simdjson8internal14base_formatterINS0_14mini_formatterEE9null_atomEv:
  205|    261|simdjson_inline void base_formatter<formatter>::null_atom() {
  206|    261|  const char * s = "null";
  207|    261|  buffer.insert(buffer.end(), s, s + 4);
  208|    261|}
_ZNK8simdjson8internal14string_builderINS0_14mini_formatterEE3strEv:
  528|  6.58k|simdjson_inline std::string_view string_builder<serializer>::str() const {
  529|  6.58k|  return format.str();
  530|  6.58k|}
_ZNK8simdjson8internal14base_formatterINS0_14mini_formatterEE3strEv:
  306|  6.58k|simdjson_inline std::string_view base_formatter<formatter>::str() const {
  307|  6.58k|  return std::string_view(buffer.data(), buffer.size());
  308|  6.58k|}

_ZN8simdjson6minifyINS_3dom7elementEEENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEET_:
  212|  6.58k|std::string minify(T x)  {
  213|  6.58k|  return to_string(x);
  214|  6.58k|}
_ZN8simdjson9to_stringINS_3dom7elementEEENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEET_:
  186|  6.58k|std::string to_string(T x)   {
  187|       |    // in C++, to_string is standard: http://www.cplusplus.com/reference/string/to_string/
  188|       |    // Currently minify and to_string are identical but in the future, they may
  189|       |    // differ.
  190|  6.58k|    simdjson::internal::string_builder<> sb;
  191|  6.58k|    sb.append(x);
  192|  6.58k|    std::string_view answer = sb.str();
  193|  6.58k|    return std::string(answer.data(), answer.size());
  194|  6.58k|}
_ZN8simdjson8internal14string_builderINS0_14mini_formatterEEC2Ev:
  115|  6.58k|  string_builder() = default;

_ZN8simdjson8internal20simdjson_result_baseINS_3dom7elementEEC2ENS_10error_codeE:
  111|  4.28k|    : simdjson_result_base(T{}, error) {}
_ZN8simdjson8internal20simdjson_result_baseINS_3dom7elementEEC2EOS3_NS_10error_codeE:
  108|  10.8k|    : std::pair<T, error_code>(std::forward<T>(value), error) {}
_ZN8simdjson8internal20simdjson_result_baseINS_3dom7elementEEC2EOS3_:
  114|  6.58k|    : simdjson_result_base(std::forward<T>(value), SUCCESS) {}
_ZNK8simdjson8internal20simdjson_result_baseINS_3dom7elementEE5errorEv:
   66|  15.1k|simdjson_inline error_code simdjson_result_base<T>::error() const noexcept {
   67|  15.1k|  return this->second;
   68|  15.1k|}

_ZN8simdjson8fallback14implementationC2Ev:
   17|      1|  simdjson_inline implementation() : simdjson::implementation(
   18|      1|      "fallback",
   19|      1|      "Generic fallback implementation",
   20|      1|      0
   21|      1|  ) {}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing18is_valid_true_atomEPKhm:
   42|     42|simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) {
   43|     42|  if (len > 4) { return is_valid_true_atom(src); }
  ------------------
  |  Branch (43:7): [True: 4, False: 38]
  ------------------
   44|     38|  else if (len == 4) { return !str4ncmp(src, "true"); }
  ------------------
  |  Branch (44:12): [True: 35, False: 3]
  ------------------
   45|      3|  else { return false; }
   46|     42|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing18is_valid_true_atomEPKh:
   37|    495|simdjson_inline bool is_valid_true_atom(const uint8_t *src) {
   38|    495|  return (str4ncmp(src, "true") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
   39|    495|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing8str4ncmpEPKhPKc:
   29|  1.61k|simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) {
   30|  1.61k|  uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++)
   31|  1.61k|  static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes");
   32|  1.61k|  std::memcpy(&srcval, src, sizeof(uint32_t));
   33|  1.61k|  return srcval ^ string_to_uint32(atom);
   34|  1.61k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing16string_to_uint32EPKc:
   23|  1.61k|simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(&val, str, sizeof(uint32_t)); return val; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing19is_valid_false_atomEPKhm:
   54|     98|simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) {
   55|     98|  if (len > 5) { return is_valid_false_atom(src); }
  ------------------
  |  Branch (55:7): [True: 43, False: 55]
  ------------------
   56|     55|  else if (len == 5) { return !str4ncmp(src+1, "alse"); }
  ------------------
  |  Branch (56:12): [True: 51, False: 4]
  ------------------
   57|      4|  else { return false; }
   58|     98|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing19is_valid_false_atomEPKh:
   49|    530|simdjson_inline bool is_valid_false_atom(const uint8_t *src) {
   50|    530|  return (str4ncmp(src+1, "alse") | jsoncharutils::is_not_structural_or_whitespace(src[5])) == 0;
   51|    530|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing18is_valid_null_atomEPKhm:
   66|     40|simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
   67|     40|  if (len > 4) { return is_valid_null_atom(src); }
  ------------------
  |  Branch (67:7): [True: 3, False: 37]
  ------------------
   68|     37|  else if (len == 4) { return !str4ncmp(src, "null"); }
  ------------------
  |  Branch (68:12): [True: 35, False: 2]
  ------------------
   69|      2|  else { return false; }
   70|     40|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_111atomparsing18is_valid_null_atomEPKh:
   61|    466|simdjson_inline bool is_valid_null_atom(const uint8_t *src) {
   62|    466|  return (str4ncmp(src, "null") | jsoncharutils::is_not_structural_or_whitespace(src[4])) == 0;
   63|    466|}

_ZN8simdjson7haswell25dom_parser_implementationC2Ev:
   58|  10.8k|inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
_ZN8simdjson7haswell25dom_parser_implementation12set_capacityEm:
   63|  10.8k|inline simdjson_warn_unused error_code dom_parser_implementation::set_capacity(size_t capacity) noexcept {
   64|  10.8k|  if(capacity > SIMDJSON_MAXSIZE_BYTES) { return CAPACITY; }
  ------------------
  |  Branch (64:6): [True: 0, False: 10.8k]
  ------------------
   65|       |  // Stage 1 index output
   66|  10.8k|  size_t max_structures = SIMDJSON_ROUNDUP_N(capacity, 64) + 2 + 7;
  ------------------
  |  |   47|  10.8k|#define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1))
  ------------------
   67|  10.8k|  structural_indexes.reset( new (std::nothrow) uint32_t[max_structures] );
   68|  10.8k|  if (!structural_indexes) { _capacity = 0; return MEMALLOC; }
  ------------------
  |  Branch (68:7): [True: 0, False: 10.8k]
  ------------------
   69|  10.8k|  structural_indexes[0] = 0;
   70|  10.8k|  n_structural_indexes = 0;
   71|       |
   72|  10.8k|  _capacity = capacity;
   73|  10.8k|  return SUCCESS;
   74|  10.8k|}
_ZN8simdjson7haswell25dom_parser_implementation13set_max_depthEm:
   76|  10.8k|inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(size_t max_depth) noexcept {
   77|       |  // Stage 2 stacks
   78|  10.8k|  open_containers.reset(new (std::nothrow) open_container[max_depth]);
   79|  10.8k|  is_array.reset(new (std::nothrow) bool[max_depth]);
   80|  10.8k|  if (!is_array || !open_containers) { _max_depth = 0; return MEMALLOC; }
  ------------------
  |  Branch (80:7): [True: 0, False: 10.8k]
  |  Branch (80:20): [True: 0, False: 10.8k]
  ------------------
   81|       |
   82|  10.8k|  _max_depth = max_depth;
   83|  10.8k|  return SUCCESS;
   84|  10.8k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_113jsoncharutils18hex_to_u32_nocheckEPKh:
   32|  11.9k|    const uint8_t *src) { // strictly speaking, static inline is a C-ism
   33|  11.9k|  uint32_t v1 = internal::digit_to_val32[630 + src[0]];
   34|  11.9k|  uint32_t v2 = internal::digit_to_val32[420 + src[1]];
   35|  11.9k|  uint32_t v3 = internal::digit_to_val32[210 + src[2]];
   36|  11.9k|  uint32_t v4 = internal::digit_to_val32[0 + src[3]];
   37|  11.9k|  return v1 | v2 | v3 | v4;
   38|  11.9k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_113jsoncharutils17codepoint_to_utf8EjPh:
   52|  10.4k|simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
   53|  10.4k|  if (cp <= 0x7F) {
  ------------------
  |  Branch (53:7): [True: 1.81k, False: 8.61k]
  ------------------
   54|  1.81k|    c[0] = uint8_t(cp);
   55|  1.81k|    return 1; // ascii
   56|  1.81k|  }
   57|  8.61k|  if (cp <= 0x7FF) {
  ------------------
  |  Branch (57:7): [True: 1.61k, False: 7.00k]
  ------------------
   58|  1.61k|    c[0] = uint8_t((cp >> 6) + 192);
   59|  1.61k|    c[1] = uint8_t((cp & 63) + 128);
   60|  1.61k|    return 2; // universal plane
   61|       |    //  Surrogates are treated elsewhere...
   62|       |    //} //else if (0xd800 <= cp && cp <= 0xdfff) {
   63|       |    //  return 0; // surrogates // could put assert here
   64|  7.00k|  } else if (cp <= 0xFFFF) {
  ------------------
  |  Branch (64:14): [True: 5.76k, False: 1.24k]
  ------------------
   65|  5.76k|    c[0] = uint8_t((cp >> 12) + 224);
   66|  5.76k|    c[1] = uint8_t(((cp >> 6) & 63) + 128);
   67|  5.76k|    c[2] = uint8_t((cp & 63) + 128);
   68|  5.76k|    return 3;
   69|  5.76k|  } else if (cp <= 0x10FFFF) { // if you know you have a valid code point, this
  ------------------
  |  Branch (69:14): [True: 1.19k, False: 47]
  ------------------
   70|       |                               // is not needed
   71|  1.19k|    c[0] = uint8_t((cp >> 18) + 240);
   72|  1.19k|    c[1] = uint8_t(((cp >> 12) & 63) + 128);
   73|  1.19k|    c[2] = uint8_t(((cp >> 6) & 63) + 128);
   74|  1.19k|    c[3] = uint8_t((cp & 63) + 128);
   75|  1.19k|    return 4;
   76|  1.19k|  }
   77|       |  // will return 0 when the code point was too large.
   78|     47|  return 0; // bad r
   79|  8.61k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_113jsoncharutils31is_not_structural_or_whitespaceEh:
   17|  5.13M|simdjson_inline uint32_t is_not_structural_or_whitespace(uint8_t c) {
   18|  5.13M|  return internal::structural_or_whitespace_negated[c];
   19|  5.13M|}

simdjson.cpp:_ZN8simdjson7haswell13numberparsing12parse_numberINS0_12_GLOBAL__N_16stage211tape_writerEEENS_10error_codeEPKhRT_:
  576|  5.13M|simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) {
  577|       |  //
  578|       |  // Check for minus sign
  579|       |  //
  580|  5.13M|  bool negative = (*src == '-');
  581|  5.13M|  const uint8_t *p = src + uint8_t(negative);
  582|       |
  583|       |  //
  584|       |  // Parse the integer part.
  585|       |  //
  586|       |  // PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
  587|  5.13M|  const uint8_t *const start_digits = p;
  588|  5.13M|  uint64_t i = 0;
  589|  27.3M|  while (parse_digit(*p, i)) { p++; }
  ------------------
  |  Branch (589:10): [True: 22.2M, False: 5.13M]
  ------------------
  590|       |
  591|       |  // If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
  592|       |  // Optimization note: size_t is expected to be unsigned.
  593|  5.13M|  size_t digit_count = size_t(p - start_digits);
  594|  5.13M|  if (digit_count == 0 || ('0' == *start_digits && digit_count > 1)) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|     73|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (594:7): [True: 43, False: 5.13M]
  |  Branch (594:28): [True: 60.4k, False: 5.07M]
  |  Branch (594:52): [True: 30, False: 60.3k]
  ------------------
  595|       |
  596|       |  //
  597|       |  // Handle floats if there is a . or e (or both)
  598|       |  //
  599|  5.13M|  int64_t exponent = 0;
  600|  5.13M|  bool is_float = false;
  601|  5.13M|  if ('.' == *p) {
  ------------------
  |  Branch (601:7): [True: 54.6k, False: 5.07M]
  ------------------
  602|  54.6k|    is_float = true;
  603|  54.6k|    ++p;
  604|  54.6k|    SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
  ------------------
  |  |  273|  54.6k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 162, False: 54.4k]
  |  |  ------------------
  ------------------
  605|  54.4k|    digit_count = int(p - start_digits); // used later to guard against overflows
  606|  54.4k|  }
  607|  5.13M|  if (('e' == *p) || ('E' == *p)) {
  ------------------
  |  Branch (607:7): [True: 25.7k, False: 5.10M]
  |  Branch (607:22): [True: 2.70M, False: 2.40M]
  ------------------
  608|  2.73M|    is_float = true;
  609|  2.73M|    ++p;
  610|  2.73M|    SIMDJSON_TRY( parse_exponent(src, p, exponent) );
  ------------------
  |  |  273|  2.73M|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 107, False: 2.73M]
  |  |  ------------------
  ------------------
  611|  2.73M|  }
  612|  5.13M|  if (is_float) {
  ------------------
  |  Branch (612:7): [True: 2.78M, False: 2.34M]
  ------------------
  613|  2.78M|    const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
  614|  2.78M|    SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
  ------------------
  |  |  273|  2.78M|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 700, False: 2.78M]
  |  |  ------------------
  ------------------
  615|  2.78M|    if (dirty_end) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|    200|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (615:9): [True: 200, False: 2.78M]
  ------------------
  616|  2.78M|    return SUCCESS;
  617|  2.78M|  }
  618|       |
  619|       |  // The longest negative 64-bit number is 19 digits.
  620|       |  // The longest positive 64-bit number is 20 digits.
  621|       |  // We do it this way so we don't trigger this branch unless we must.
  622|  2.34M|  size_t longest_digit_count = negative ? 19 : 20;
  ------------------
  |  Branch (622:32): [True: 4.40k, False: 2.34M]
  ------------------
  623|  2.34M|  if (digit_count > longest_digit_count) { return BIGINT_NUMBER(src); }
  ------------------
  |  |   29|     73|#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
  ------------------
  |  Branch (623:7): [True: 73, False: 2.34M]
  ------------------
  624|  2.34M|  if (digit_count == longest_digit_count) {
  ------------------
  |  Branch (624:7): [True: 1.72k, False: 2.34M]
  ------------------
  625|  1.72k|    if (negative) {
  ------------------
  |  Branch (625:9): [True: 691, False: 1.03k]
  ------------------
  626|       |      // Anything negative above INT64_MAX+1 is invalid
  627|    691|      if (i > uint64_t(INT64_MAX)+1) { return BIGINT_NUMBER(src);  }
  ------------------
  |  |   29|     44|#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
  ------------------
  |  Branch (627:11): [True: 44, False: 647]
  ------------------
  628|    647|      WRITE_INTEGER(~i+1, src, writer);
  ------------------
  |  |   26|    647|#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
  ------------------
  629|    647|      if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|      5|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (629:11): [True: 5, False: 642]
  ------------------
  630|    642|      return SUCCESS;
  631|       |    // Positive overflow check:
  632|       |    // - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
  633|       |    //   biggest uint64_t.
  634|       |    // - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
  635|       |    //   If we got here, it's a 20 digit number starting with the digit "1".
  636|       |    // - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
  637|       |    //   than 1,553,255,926,290,448,384.
  638|       |    // - That is smaller than the smallest possible 20-digit number the user could write:
  639|       |    //   10,000,000,000,000,000,000.
  640|       |    // - Therefore, if the number is positive and lower than that, it's overflow.
  641|       |    // - The value we are looking at is less than or equal to INT64_MAX.
  642|       |    //
  643|  1.03k|    }  else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|     73|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (643:17): [True: 7, False: 1.02k]
  |  Branch (643:43): [True: 66, False: 959]
  ------------------
  644|  1.72k|  }
  645|       |
  646|       |  // Write unsigned if it does not fit in a signed integer.
  647|  2.34M|  if (i > uint64_t(INT64_MAX)) {
  ------------------
  |  Branch (647:7): [True: 1.88k, False: 2.34M]
  ------------------
  648|  1.88k|    WRITE_UNSIGNED(i, src, writer);
  ------------------
  |  |   27|  1.88k|#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
  ------------------
  649|  2.34M|  } else {
  650|       |#if SIMDJSON_MINUS_ZERO_AS_FLOAT
  651|       |    if(i == 0 && negative) {
  652|       |      // We have to write -0.0 instead of 0
  653|       |      WRITE_DOUBLE(-0.0, src, writer);
  654|       |    } else {
  655|       |      WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
  656|       |    }
  657|       |#else
  658|  2.34M|  WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
  ------------------
  |  |   26|  4.69M|#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
  |  |  ------------------
  |  |  |  Branch (26:64): [True: 3.70k, False: 2.34M]
  |  |  ------------------
  ------------------
  659|  2.34M|#endif
  660|  2.34M|  }
  661|  2.34M|  if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|     66|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (661:7): [True: 66, False: 2.34M]
  ------------------
  662|  2.34M|  return SUCCESS;
  663|  2.34M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_111parse_digitImEEbhRT_:
  350|  30.9M|simdjson_inline bool parse_digit(const uint8_t c, I &i) {
  351|  30.9M|  const uint8_t digit = static_cast<uint8_t>(c - '0');
  352|  30.9M|  if (digit > 9) {
  ------------------
  |  Branch (352:7): [True: 5.19M, False: 25.8M]
  ------------------
  353|  5.19M|    return false;
  354|  5.19M|  }
  355|       |  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
  356|  25.8M|  i = 10 * i + digit; // might overflow, we will handle the overflow later
  357|  25.8M|  return true;
  358|  30.9M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_129parse_decimal_after_separatorEPKhRS4_RmRl:
  364|  54.6k|simdjson_inline error_code parse_decimal_after_separator(simdjson_unused const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
  365|       |  // we continue with the fiction that we have an integer. If the
  366|       |  // floating point number is representable as x * 10^z for some integer
  367|       |  // z that fits in 53 bits, then we will be able to convert back the
  368|       |  // the integer into a float in a lossless manner.
  369|  54.6k|  const uint8_t *const first_after_period = p;
  370|       |
  371|  54.6k|#ifdef SIMDJSON_SWAR_NUMBER_PARSING
  372|  54.6k|#if SIMDJSON_SWAR_NUMBER_PARSING
  373|       |  // this helps if we have lots of decimals!
  374|       |  // this turns out to be frequent enough.
  375|  54.6k|  if (is_made_of_eight_digits_fast(p)) {
  ------------------
  |  Branch (375:7): [True: 9.07k, False: 45.5k]
  ------------------
  376|  9.07k|    i = i * 100000000 + parse_eight_digits_unrolled(p);
  377|  9.07k|    p += 8;
  378|  9.07k|  }
  379|  54.6k|#endif // SIMDJSON_SWAR_NUMBER_PARSING
  380|  54.6k|#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
  381|       |  // Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
  382|  54.6k|  if (parse_digit(*p, i)) { ++p; }
  ------------------
  |  Branch (382:7): [True: 52.9k, False: 1.73k]
  ------------------
  383|  3.56M|  while (parse_digit(*p, i)) { p++; }
  ------------------
  |  Branch (383:10): [True: 3.51M, False: 54.6k]
  ------------------
  384|  54.6k|  exponent = first_after_period - p;
  385|       |  // Decimal without digits (123.) is illegal
  386|  54.6k|  if (exponent == 0) {
  ------------------
  |  Branch (386:7): [True: 162, False: 54.4k]
  ------------------
  387|    162|    return INVALID_NUMBER(src);
  ------------------
  |  |   25|    162|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  388|    162|  }
  389|  54.4k|  return SUCCESS;
  390|  54.6k|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_128is_made_of_eight_digits_fastEPKh:
  333|  54.6k|simdjson_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
  334|  54.6k|  uint64_t val;
  335|       |  // this can read up to 7 bytes beyond the buffer size, but we require
  336|       |  // SIMDJSON_PADDING of padding
  337|  54.6k|  static_assert(7 <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be bigger than 7");
  338|  54.6k|  std::memcpy(&val, chars, 8);
  339|       |  // a branchy method might be faster:
  340|       |  // return (( val & 0xF0F0F0F0F0F0F0F0 ) == 0x3030303030303030)
  341|       |  //  && (( (val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0 ) ==
  342|       |  //  0x3030303030303030);
  343|  54.6k|  return (((val & 0xF0F0F0F0F0F0F0F0) |
  344|  54.6k|           (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
  345|  54.6k|          0x3333333333333333);
  346|  54.6k|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_114parse_exponentEPKhRS4_Rl:
  392|  2.73M|simdjson_inline error_code parse_exponent(simdjson_unused const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
  393|       |  // Exp Sign: -123.456e[-]78
  394|  2.73M|  bool neg_exp = ('-' == *p);
  395|  2.73M|  if (neg_exp || '+' == *p) { p++; } // Skip + as well
  ------------------
  |  Branch (395:7): [True: 40.2k, False: 2.69M]
  |  Branch (395:18): [True: 1.47k, False: 2.69M]
  ------------------
  396|       |
  397|       |  // Exponent: -123.456e-[78]
  398|  2.73M|  auto start_exp = p;
  399|  2.73M|  int64_t exp_number = 0;
  400|  12.6M|  while (parse_digit(*p, exp_number)) { ++p; }
  ------------------
  |  Branch (400:10): [True: 9.87M, False: 2.73M]
  ------------------
  401|       |  // It is possible for parse_digit to overflow.
  402|       |  // In particular, it could overflow to INT64_MIN, and we cannot do - INT64_MIN.
  403|       |  // Thus we *must* check for possible overflow before we negate exp_number.
  404|       |
  405|       |  // Performance notes: it may seem like combining the two "simdjson_unlikely checks" below into
  406|       |  // a single simdjson_unlikely path would be faster. The reasoning is sound, but the compiler may
  407|       |  // not oblige and may, in fact, generate two distinct paths in any case. It might be
  408|       |  // possible to do uint64_t(p - start_exp - 1) >= 18 but it could end up trading off
  409|       |  // instructions for a simdjson_likely branch, an unconclusive gain.
  410|       |
  411|       |  // If there were no digits, it's an error.
  412|  2.73M|  if (simdjson_unlikely(p == start_exp)) {
  ------------------
  |  |  106|  2.73M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 107, False: 2.73M]
  |  |  ------------------
  ------------------
  413|    107|    return INVALID_NUMBER(src);
  ------------------
  |  |   25|    107|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  414|    107|  }
  415|       |  // We have a valid positive exponent in exp_number at this point, except that
  416|       |  // it may have overflowed.
  417|       |
  418|       |  // If there were more than 18 digits, we may have overflowed the integer. We have to do
  419|       |  // something!!!!
  420|  2.73M|  if (simdjson_unlikely(p > start_exp+18)) {
  ------------------
  |  |  106|  2.73M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 853, False: 2.73M]
  |  |  ------------------
  ------------------
  421|       |    // Skip leading zeroes: 1e000000000000000000001 is technically valid and does not overflow
  422|   213k|    while (*start_exp == '0') { start_exp++; }
  ------------------
  |  Branch (422:12): [True: 212k, False: 853]
  ------------------
  423|       |    // 19 digits could overflow int64_t and is kind of absurd anyway. We don't
  424|       |    // support exponents smaller than -999,999,999,999,999,999 and bigger
  425|       |    // than 999,999,999,999,999,999.
  426|       |    // We can truncate.
  427|       |    // Note that 999999999999999999 is assuredly too large. The maximal ieee64 value before
  428|       |    // infinity is ~1.8e308. The smallest subnormal is ~5e-324. So, actually, we could
  429|       |    // truncate at 324.
  430|       |    // Note that there is no reason to fail per se at this point in time.
  431|       |    // E.g., 0e999999999999999999999 is a fine number.
  432|    853|    if (p > start_exp+18) { exp_number = 999999999999999999; }
  ------------------
  |  Branch (432:9): [True: 435, False: 418]
  ------------------
  433|    853|  }
  434|       |  // At this point, we know that exp_number is a sane, positive, signed integer.
  435|       |  // It is <= 999,999,999,999,999,999. As long as 'exponent' is in
  436|       |  // [-8223372036854775808, 8223372036854775808], we won't overflow. Because 'exponent'
  437|       |  // is bounded in magnitude by the size of the JSON input, we are fine in this universe.
  438|       |  // To sum it up: the next line should never overflow.
  439|  2.73M|  exponent += (neg_exp ? -exp_number : exp_number);
  ------------------
  |  Branch (439:16): [True: 40.2k, False: 2.69M]
  ------------------
  440|  2.73M|  return SUCCESS;
  441|  2.73M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_111parse_digitIlEEbhRT_:
  350|  12.6M|simdjson_inline bool parse_digit(const uint8_t c, I &i) {
  351|  12.6M|  const uint8_t digit = static_cast<uint8_t>(c - '0');
  352|  12.6M|  if (digit > 9) {
  ------------------
  |  Branch (352:7): [True: 2.73M, False: 9.87M]
  ------------------
  353|  2.73M|    return false;
  354|  2.73M|  }
  355|       |  // PERF NOTE: multiplication by 10 is cheaper than arbitrary integer multiplication
  356|  9.87M|  i = 10 * i + digit; // might overflow, we will handle the overflow later
  357|  9.87M|  return true;
  358|  12.6M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing11write_floatINS0_12_GLOBAL__N_16stage211tape_writerEEENS_10error_codeEPKhbmS8_mlRT_:
  481|  2.78M|simdjson_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer) {
  482|       |  // If we frequently had to deal with long strings of digits,
  483|       |  // we could extend our code by using a 128-bit integer instead
  484|       |  // of a 64-bit integer. However, this is uncommon in practice.
  485|       |  //
  486|       |  // 9999999999999999999 < 2**64 so we can accommodate 19 digits.
  487|       |  // If we have a decimal separator, then digit_count - 1 is the number of digits, but we
  488|       |  // may not have a decimal separator!
  489|  2.78M|  if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
  ------------------
  |  |  106|  2.79M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 7.12k, False: 2.77M]
  |  |  |  Branch (106:52): [True: 7.42k, False: 2.77M]
  |  |  |  Branch (106:52): [True: 7.12k, False: 305]
  |  |  ------------------
  ------------------
  490|       |    // Ok, chances are good that we had an overflow!
  491|       |    // this is almost never going to get called!!!
  492|       |    // we start anew, going slowly!!!
  493|       |    // This will happen in the following examples:
  494|       |    // 10000000000000000000000000000000000000000000e+308
  495|       |    // 3.1415926535897932384626433832795028841971693993751
  496|       |    //
  497|       |    // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
  498|       |    // reference to it, it would force it to be stored in memory, preventing the compiler from
  499|       |    // picking it apart and putting into registers. i.e. if we pass it as reference,
  500|       |    // it gets slow.
  501|  7.12k|    double d;
  502|  7.12k|    error_code error = slow_float_parsing(src, &d);
  503|  7.12k|    writer.append_double(d);
  504|  7.12k|    return error;
  505|  7.12k|  }
  506|       |  // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
  507|       |  // way we've tried: https://github.com/simdjson/simdjson/pull/990#discussion_r448497331
  508|       |  // To future reader: we'd love if someone found a better way, or at least could explain this result!
  509|  2.77M|  if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
  ------------------
  |  |  106|  5.55M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 10.9k, False: 2.76M]
  |  |  ------------------
  ------------------
  |  Branch (509:75): [True: 1.25k, False: 2.76M]
  ------------------
  510|       |    //
  511|       |    // Important: smallest_power is such that it leads to a zero value.
  512|       |    // Observe that 18446744073709551615e-343 == 0, i.e. (2**64 - 1) e -343 is zero
  513|       |    // so something x 10^-343 goes to zero, but not so with  something x 10^-342.
  514|  12.2k|    static_assert(simdjson::internal::smallest_power <= -342, "smallest_power is not small enough");
  515|       |    //
  516|  12.2k|    if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
  ------------------
  |  Branch (516:8): [True: 10.9k, False: 1.25k]
  |  Branch (516:59): [True: 891, False: 359]
  ------------------
  517|       |      // E.g. Parse "-0.0e-999" into the same value as "-0.0". See https://en.wikipedia.org/wiki/Signed_zero
  518|  11.8k|      WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
  ------------------
  |  |   28|  23.6k|#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
  |  |  ------------------
  |  |  |  Branch (28:66): [True: 12, False: 11.8k]
  |  |  ------------------
  ------------------
  519|  11.8k|      return SUCCESS;
  520|  11.8k|    } else { // (exponent > largest_power) and (i != 0)
  521|       |      // We have, for sure, an infinite value and simdjson refuses to parse infinite values.
  522|    359|      return INVALID_NUMBER(src);
  ------------------
  |  |   25|    359|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  523|    359|    }
  524|  12.2k|  }
  525|  2.76M|  double d;
  526|  2.76M|  if (!compute_float_64(exponent, i, negative, d)) {
  ------------------
  |  Branch (526:7): [True: 186, False: 2.76M]
  ------------------
  527|       |    // we are almost never going to get here.
  528|    186|    if (!parse_float_fallback(src, &d)) { return INVALID_NUMBER(src); }
  ------------------
  |  |   25|    186|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  |  Branch (528:9): [True: 186, False: 0]
  ------------------
  529|    186|  }
  530|  2.76M|  WRITE_DOUBLE(d, src, writer);
  ------------------
  |  |   28|  2.76M|#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
  ------------------
  531|  2.76M|  return SUCCESS;
  532|  2.76M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_118significant_digitsEPKhm:
  460|  7.42k|simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t digit_count) {
  461|       |  // It is possible that the integer had an overflow.
  462|       |  // We have to handle the case where we have 0.0000somenumber.
  463|  7.42k|  const uint8_t *start = start_digits;
  464|  3.95M|  while ((*start == '0') || (*start == '.')) { ++start; }
  ------------------
  |  Branch (464:10): [True: 3.94M, False: 12.7k]
  |  Branch (464:29): [True: 5.35k, False: 7.42k]
  ------------------
  465|       |  // we over-decrement by one when there is a '.'
  466|  7.42k|  return digit_count - size_t(start - start_digits);
  467|  7.42k|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsingL18slow_float_parsingEPKhPd:
  472|  7.12k|static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
  473|  7.12k|  if (parse_float_fallback(src, answer)) {
  ------------------
  |  Branch (473:7): [True: 6.96k, False: 155]
  ------------------
  474|  6.96k|    return SUCCESS;
  475|  6.96k|  }
  476|    155|  return INVALID_NUMBER(src);
  ------------------
  |  |   25|    155|#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
  ------------------
  477|  7.12k|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_116compute_float_64ElmbRd:
   52|  2.76M|simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, double &d) {
   53|       |  // we start with a fast path
   54|       |  // It was described in
   55|       |  // Clinger WD. How to read floating point numbers accurately.
   56|       |  // ACM SIGPLAN Notices. 1990
   57|       |#ifndef FLT_EVAL_METHOD
   58|       |#error "FLT_EVAL_METHOD should be defined, please include cfloat."
   59|       |#endif
   60|       |#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
   61|       |  // We cannot be certain that x/y is rounded to nearest.
   62|       |  if (0 <= power && power <= 22 && i <= 9007199254740991)
   63|       |#else
   64|  2.76M|  if (-22 <= power && power <= 22 && i <= 9007199254740991)
  ------------------
  |  Branch (64:7): [True: 2.74M, False: 22.5k]
  |  Branch (64:23): [True: 102k, False: 2.64M]
  |  Branch (64:38): [True: 100k, False: 1.44k]
  ------------------
   65|   100k|#endif
   66|   100k|  {
   67|       |    // convert the integer into a double. This is lossless since
   68|       |    // 0 <= i <= 2^53 - 1.
   69|   100k|    d = double(i);
   70|       |    //
   71|       |    // The general idea is as follows.
   72|       |    // If 0 <= s < 2^53 and if 10^0 <= p <= 10^22 then
   73|       |    // 1) Both s and p can be represented exactly as 64-bit floating-point
   74|       |    // values
   75|       |    // (binary64).
   76|       |    // 2) Because s and p can be represented exactly as floating-point values,
   77|       |    // then s * p
   78|       |    // and s / p will produce correctly rounded values.
   79|       |    //
   80|   100k|    if (power < 0) {
  ------------------
  |  Branch (80:9): [True: 52.4k, False: 48.4k]
  ------------------
   81|  52.4k|      d = d / simdjson::internal::power_of_ten[-power];
   82|  52.4k|    } else {
   83|  48.4k|      d = d * simdjson::internal::power_of_ten[power];
   84|  48.4k|    }
   85|   100k|    if (negative) {
  ------------------
  |  Branch (85:9): [True: 34.8k, False: 66.0k]
  ------------------
   86|  34.8k|      d = -d;
   87|  34.8k|    }
   88|   100k|    return true;
   89|   100k|  }
   90|       |  // When 22 < power && power <  22 + 16, we could
   91|       |  // hope for another, secondary fast path.  It was
   92|       |  // described by David M. Gay in  "Correctly rounded
   93|       |  // binary-decimal and decimal-binary conversions." (1990)
   94|       |  // If you need to compute i * 10^(22 + x) for x < 16,
   95|       |  // first compute i * 10^x, if you know that result is exact
   96|       |  // (e.g., when i * 10^x < 2^53),
   97|       |  // then you can still proceed and do (i * 10^x) * 10^22.
   98|       |  // Is this worth your time?
   99|       |  // You need  22 < power *and* power <  22 + 16 *and* (i * 10^(x-22) < 2^53)
  100|       |  // for this second fast path to work.
  101|       |  // If you you have 22 < power *and* power <  22 + 16, and then you
  102|       |  // optimistically compute "i * 10^(x-22)", there is still a chance that you
  103|       |  // have wasted your time if i * 10^(x-22) >= 2^53. It makes the use cases of
  104|       |  // this optimization maybe less common than we would like. Source:
  105|       |  // http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
  106|       |  // also used in RapidJSON: https://rapidjson.org/strtod_8h_source.html
  107|       |
  108|       |  // The fast path has now failed, so we are failing back on the slower path.
  109|       |
  110|       |  // In the slow path, we need to adjust i so that it is > 1<<63 which is always
  111|       |  // possible, except if i == 0, so we handle i == 0 separately.
  112|  2.66M|  if(i == 0) {
  ------------------
  |  Branch (112:6): [True: 1.69k, False: 2.66M]
  ------------------
  113|  1.69k|    d = negative ? -0.0 : 0.0;
  ------------------
  |  Branch (113:9): [True: 16, False: 1.67k]
  ------------------
  114|  1.69k|    return true;
  115|  1.69k|  }
  116|       |
  117|       |
  118|       |  // The exponent is 1024 + 63 + power
  119|       |  //     + floor(log(5**power)/log(2)).
  120|       |  // The 1024 comes from the ieee64 standard.
  121|       |  // The 63 comes from the fact that we use a 64-bit word.
  122|       |  //
  123|       |  // Computing floor(log(5**power)/log(2)) could be
  124|       |  // slow. Instead we use a fast function.
  125|       |  //
  126|       |  // For power in (-400,350), we have that
  127|       |  // (((152170 + 65536) * power ) >> 16);
  128|       |  // is equal to
  129|       |  //  floor(log(5**power)/log(2)) + power when power >= 0
  130|       |  // and it is equal to
  131|       |  //  ceil(log(5**-power)/log(2)) + power when power < 0
  132|       |  //
  133|       |  // The 65536 is (1<<16) and corresponds to
  134|       |  // (65536 * power) >> 16 ---> power
  135|       |  //
  136|       |  // ((152170 * power ) >> 16) is equal to
  137|       |  // floor(log(5**power)/log(2))
  138|       |  //
  139|       |  // Note that this is not magic: 152170/(1<<16) is
  140|       |  // approximately equal to log(5)/log(2).
  141|       |  // The 1<<16 value is a power of two; we could use a
  142|       |  // larger power of 2 if we wanted to.
  143|       |  //
  144|  2.66M|  int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
  145|       |
  146|       |
  147|       |  // We want the most significant bit of i to be 1. Shift if needed.
  148|  2.66M|  int lz = leading_zeroes(i);
  149|  2.66M|  i <<= lz;
  150|       |
  151|       |
  152|       |  // We are going to need to do some 64-bit arithmetic to get a precise product.
  153|       |  // We use a table lookup approach.
  154|       |  // It is safe because
  155|       |  // power >= smallest_power
  156|       |  // and power <= largest_power
  157|       |  // We recover the mantissa of the power, it has a leading 1. It is always
  158|       |  // rounded down.
  159|       |  //
  160|       |  // We want the most significant 64 bits of the product. We know
  161|       |  // this will be non-zero because the most significant bit of i is
  162|       |  // 1.
  163|  2.66M|  const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
  164|       |  // Optimization: It may be that materializing the index as a variable might confuse some compilers and prevent effective complex-addressing loads. (Done for code clarity.)
  165|       |  //
  166|       |  // The full_multiplication function computes the 128-bit product of two 64-bit words
  167|       |  // with a returned value of type value128 with a "low component" corresponding to the
  168|       |  // 64-bit least significant bits of the product and with a "high component" corresponding
  169|       |  // to the 64-bit most significant bits of the product.
  170|  2.66M|  simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
  171|       |  // Both i and power_of_five_128[index] have their most significant bit set to 1 which
  172|       |  // implies that the either the most or the second most significant bit of the product
  173|       |  // is 1. We pack values in this manner for efficiency reasons: it maximizes the use
  174|       |  // we make of the product. It also makes it easy to reason about the product: there
  175|       |  // is 0 or 1 leading zero in the product.
  176|       |
  177|       |  // Unless the least significant 9 bits of the high (64-bit) part of the full
  178|       |  // product are all 1s, then we know that the most significant 55 bits are
  179|       |  // exact and no further work is needed. Having 55 bits is necessary because
  180|       |  // we need 53 bits for the mantissa but we have to have one rounding bit and
  181|       |  // we can waste a bit if the most significant bit of the product is zero.
  182|  2.66M|  if((firstproduct.high & 0x1FF) == 0x1FF) {
  ------------------
  |  Branch (182:6): [True: 1.61k, False: 2.66M]
  ------------------
  183|       |    // We want to compute i * 5^q, but only care about the top 55 bits at most.
  184|       |    // Consider the scenario where q>=0. Then 5^q may not fit in 64-bits. Doing
  185|       |    // the full computation is wasteful. So we do what is called a "truncated
  186|       |    // multiplication".
  187|       |    // We take the most significant 64-bits, and we put them in
  188|       |    // power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
  189|       |    // to the desired approximation using one multiplication. Sometimes it does not suffice.
  190|       |    // Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
  191|       |    // then we get a better approximation to i * 5^q.
  192|       |    //
  193|       |    // That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
  194|       |    // more complicated.
  195|       |    //
  196|       |    // There is an extra layer of complexity in that we need more than 55 bits of
  197|       |    // accuracy in the round-to-even scenario.
  198|       |    //
  199|       |    // The full_multiplication function computes the 128-bit product of two 64-bit words
  200|       |    // with a returned value of type value128 with a "low component" corresponding to the
  201|       |    // 64-bit least significant bits of the product and with a "high component" corresponding
  202|       |    // to the 64-bit most significant bits of the product.
  203|  1.61k|    simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
  204|  1.61k|    firstproduct.low += secondproduct.high;
  205|  1.61k|    if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
  ------------------
  |  Branch (205:8): [True: 839, False: 773]
  ------------------
  206|       |    // As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
  207|       |    // Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
  208|       |    // is sufficiently accurate, and more computation is not needed.
  209|  1.61k|  }
  210|  2.66M|  uint64_t lower = firstproduct.low;
  211|  2.66M|  uint64_t upper = firstproduct.high;
  212|       |  // The final mantissa should be 53 bits with a leading 1.
  213|       |  // We shift it so that it occupies 54 bits with a leading 1.
  214|       |  ///////
  215|  2.66M|  uint64_t upperbit = upper >> 63;
  216|  2.66M|  uint64_t mantissa = upper >> (upperbit + 9);
  217|  2.66M|  lz += int(1 ^ upperbit);
  218|       |
  219|       |  // Here we have mantissa < (1<<54).
  220|  2.66M|  int64_t real_exponent = exponent - lz;
  221|  2.66M|  if (simdjson_unlikely(real_exponent <= 0)) { // we have a subnormal?
  ------------------
  |  |  106|  2.66M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 21.2k, False: 2.64M]
  |  |  ------------------
  ------------------
  222|       |    // Here have that real_exponent <= 0 so -real_exponent >= 0
  223|  21.2k|    if(-real_exponent + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure.
  ------------------
  |  Branch (223:8): [True: 830, False: 20.3k]
  ------------------
  224|    830|      d = negative ? -0.0 : 0.0;
  ------------------
  |  Branch (224:11): [True: 15, False: 815]
  ------------------
  225|    830|      return true;
  226|    830|    }
  227|       |    // next line is safe because -real_exponent + 1 < 0
  228|  20.3k|    mantissa >>= -real_exponent + 1;
  229|       |    // Thankfully, we can't have both "round-to-even" and subnormals because
  230|       |    // "round-to-even" only occurs for powers close to 0.
  231|  20.3k|    mantissa += (mantissa & 1); // round up
  232|  20.3k|    mantissa >>= 1;
  233|       |    // There is a weird scenario where we don't have a subnormal but just.
  234|       |    // Suppose we start with 2.2250738585072013e-308, we end up
  235|       |    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
  236|       |    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
  237|       |    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
  238|       |    // subnormal, but we can only know this after rounding.
  239|       |    // So we only declare a subnormal if we are smaller than the threshold.
  240|  20.3k|    real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
  ------------------
  |  Branch (240:21): [True: 20.3k, False: 3]
  ------------------
  241|  20.3k|    d = to_double(mantissa, real_exponent, negative);
  242|  20.3k|    return true;
  243|  21.2k|  }
  244|       |  // We have to round to even. The "to even" part
  245|       |  // is only a problem when we are right in between two floats
  246|       |  // which we guard against.
  247|       |  // If we have lots of trailing zeros, we may fall right between two
  248|       |  // floating-point values.
  249|       |  //
  250|       |  // The round-to-even cases take the form of a number 2m+1 which is in (2^53,2^54]
  251|       |  // times a power of two. That is, it is right between a number with binary significand
  252|       |  // m and another number with binary significand m+1; and it must be the case
  253|       |  // that it cannot be represented by a float itself.
  254|       |  //
  255|       |  // We must have that w * 10 ^q == (2m+1) * 2^p for some power of two 2^p.
  256|       |  // Recall that 10^q = 5^q * 2^q.
  257|       |  // When q >= 0, we must have that (2m+1) is divible by 5^q, so 5^q <= 2^54. We have that
  258|       |  //  5^23 <=  2^54 and it is the last power of five to qualify, so q <= 23.
  259|       |  // When q<0, we have  w  >=  (2m+1) x 5^{-q}.  We must have that w<2^{64} so
  260|       |  // (2m+1) x 5^{-q} < 2^{64}. We have that 2m+1>2^{53}. Hence, we must have
  261|       |  // 2^{53} x 5^{-q} < 2^{64}.
  262|       |  // Hence we have 5^{-q} < 2^{11}$ or q>= -4.
  263|       |  //
  264|       |  // We require lower <= 1 and not lower == 0 because we could not prove that
  265|       |  // that lower == 0 is implied; but we could prove that lower <= 1 is a necessary and sufficient test.
  266|  2.64M|  if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
  ------------------
  |  |  106|  15.8M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 2.62M, False: 17.8k]
  |  |  |  Branch (106:52): [True: 2.63M, False: 6.86k]
  |  |  |  Branch (106:52): [True: 2.63M, False: 921]
  |  |  |  Branch (106:52): [True: 2.62M, False: 8.70k]
  |  |  |  Branch (106:52): [True: 2.62M, False: 1.38k]
  |  |  ------------------
  ------------------
  267|  2.62M|    if((mantissa  << (upperbit + 64 - 53 - 2)) ==  upper) {
  ------------------
  |  Branch (267:8): [True: 2.62M, False: 2.25k]
  ------------------
  268|  2.62M|      mantissa &= ~1;             // flip it so that we do not round up
  269|  2.62M|    }
  270|  2.62M|  }
  271|       |
  272|  2.64M|  mantissa += mantissa & 1;
  273|  2.64M|  mantissa >>= 1;
  274|       |
  275|       |  // Here we have mantissa < (1<<53), unless there was an overflow
  276|  2.64M|  if (mantissa >= (1ULL << 53)) {
  ------------------
  |  Branch (276:7): [True: 413, False: 2.64M]
  ------------------
  277|       |    //////////
  278|       |    // This will happen when parsing values such as 7.2057594037927933e+16
  279|       |    ////////
  280|    413|    mantissa = (1ULL << 52);
  281|    413|    real_exponent++;
  282|    413|  }
  283|  2.64M|  mantissa &= ~(1ULL << 52);
  284|       |  // we have to check that real_exponent is in range, otherwise we bail out
  285|  2.64M|  if (simdjson_unlikely(real_exponent > 2046)) {
  ------------------
  |  |  106|  2.64M|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 186, False: 2.64M]
  |  |  ------------------
  ------------------
  286|       |    // We have an infinite value!!! We could actually throw an error here if we could.
  287|    186|    return false;
  288|    186|  }
  289|  2.64M|  d = to_double(mantissa, real_exponent, negative);
  290|  2.64M|  return true;
  291|  2.64M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_19to_doubleEmmb:
   37|  2.66M|simdjson_inline double to_double(uint64_t mantissa, uint64_t real_exponent, bool negative) {
   38|  2.66M|    double d;
   39|  2.66M|    mantissa &= ~(1ULL << 52);
   40|  2.66M|    mantissa |= real_exponent << 52;
   41|  2.66M|    mantissa |= ((static_cast<uint64_t>(negative)) << 63);
   42|  2.66M|    std::memcpy(&d, &mantissa, sizeof(d));
   43|  2.66M|    return d;
   44|  2.66M|}
simdjson.cpp:_ZN8simdjson7haswell13numberparsing12_GLOBAL__N_120parse_float_fallbackEPKhPd:
  300|  7.30k|static bool parse_float_fallback(const uint8_t *ptr, double *outDouble) {
  301|  7.30k|  *outDouble = simdjson::internal::from_chars(reinterpret_cast<const char *>(ptr));
  302|       |  // We do not accept infinite values.
  303|       |
  304|       |  // Detecting finite values in a portable manner is ridiculously hard, ideally
  305|       |  // we would want to do:
  306|       |  // return !std::isfinite(*outDouble);
  307|       |  // but that mysteriously fails under legacy/old libc++ libraries, see
  308|       |  // https://github.com/simdjson/simdjson/issues/1286
  309|       |  //
  310|       |  // Therefore, fall back to this solution (the extra parens are there
  311|       |  // to handle that max may be a macro on windows).
  312|  7.30k|  return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
  ------------------
  |  Branch (312:12): [True: 329, False: 6.97k]
  |  Branch (312:65): [True: 12, False: 6.96k]
  ------------------
  313|  7.30k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115trailing_zeroesEm:
   22|  13.9M|simdjson_inline int trailing_zeroes(uint64_t input_num) {
   23|       |#if SIMDJSON_REGULAR_VISUAL_STUDIO
   24|       |  return (int)_tzcnt_u64(input_num);
   25|       |#else // SIMDJSON_REGULAR_VISUAL_STUDIO
   26|       |  ////////
   27|       |  // You might expect the next line to be equivalent to
   28|       |  // return (int)_tzcnt_u64(input_num);
   29|       |  // but the generated code differs and might be less efficient?
   30|       |  ////////
   31|  13.9M|  return __builtin_ctzll(input_num);
   32|  13.9M|#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
   33|  13.9M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_110count_onesEm:
   51|   407k|simdjson_inline long long int count_ones(uint64_t input_num) {
   52|   407k|  return _popcnt64(input_num);
   53|   407k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_116clear_lowest_bitEm:
   36|  13.6M|simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
   37|  13.6M|  return _blsr_u64(input_num);
   38|  13.6M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_114leading_zeroesEm:
   41|  2.66M|simdjson_inline int leading_zeroes(uint64_t input_num) {
   42|  2.66M|  return int(_lzcnt_u64(input_num));
   43|  2.66M|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_110prefix_xorEm:
   18|  1.54M|simdjson_inline uint64_t prefix_xor(const uint64_t bitmask) {
   19|       |  // There should be no such thing with a processor supporting avx2
   20|       |  // but not clmul.
   21|  1.54M|  __m128i all_ones = _mm_set1_epi8('\xFF');
   22|  1.54M|  __m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, bitmask), all_ones, 0);
   23|  1.54M|  return _mm_cvtsi128_si64(result);
   24|  1.54M|}

_ZN8simdjson7haswell14implementationC2Ev:
   19|      1|  simdjson_inline implementation() : simdjson::implementation(
   20|      1|      "haswell",
   21|      1|      "Intel/AMD AVX2",
   22|      1|      internal::instruction_set::AVX2 | internal::instruction_set::PCLMULQDQ | internal::instruction_set::BMI1 | internal::instruction_set::BMI2
   23|      1|  ) {}

simdjson.cpp:_ZN8simdjson7haswell13numberparsingL27parse_eight_digits_unrolledEPKh:
   18|  9.07k|static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
   19|       |  // this actually computes *16* values so we are being wasteful.
   20|  9.07k|  const __m128i ascii0 = _mm_set1_epi8('0');
   21|  9.07k|  const __m128i mul_1_10 =
   22|  9.07k|      _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1);
   23|  9.07k|  const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1);
   24|  9.07k|  const __m128i mul_1_10000 =
   25|  9.07k|      _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1);
   26|  9.07k|  const __m128i input = _mm_sub_epi8(
   27|  9.07k|      _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0);
   28|  9.07k|  const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10);
   29|  9.07k|  const __m128i t2 = _mm_madd_epi16(t1, mul_1_100);
   30|  9.07k|  const __m128i t3 = _mm_packus_epi32(t2, t2);
   31|  9.07k|  const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000);
   32|  9.07k|  return _mm_cvtsi128_si32(
   33|  9.07k|      t4); // only captures the sum of the first 8 digits, drop the rest
   34|  9.07k|}
_ZN8simdjson7haswell13numberparsing19full_multiplicationEmm:
   37|  2.66M|simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
   38|  2.66M|  internal::value128 answer;
   39|       |#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
   40|       |#if SIMDJSON_IS_ARM64
   41|       |  // ARM64 has native support for 64-bit multiplications, no need to emultate
   42|       |  answer.high = __umulh(value1, value2);
   43|       |  answer.low = value1 * value2;
   44|       |#else
   45|       |  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
   46|       |#endif // SIMDJSON_IS_ARM64
   47|       |#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
   48|  2.66M|  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
   49|  2.66M|  answer.low = uint64_t(r);
   50|  2.66M|  answer.high = uint64_t(r >> 64);
   51|  2.66M|#endif
   52|  2.66M|  return answer;
   53|  2.66M|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEC2Ev:
  231|  32.5k|    simdjson_inline simd8() : base8_numeric<uint8_t>() {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhEC2Ev:
   98|  32.5k|    simdjson_inline base8_numeric() : base8<T>() {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5base8IhNS2_5simd8IbEEEC2Ev:
   50|  32.5k|    simdjson_inline base8() : base<simd8<T>>() {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEC2Ev:
   22|  32.5k|    simdjson_inline base() : value{__m256i()} {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhEC2EPKh:
  309|  1.54M|    simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+32)} {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhE4loadEPKh:
   82|  4.22M|    static simdjson_inline simd8<T> load(const T values[32]) {
   83|  4.22M|      return _mm256_loadu_si256(reinterpret_cast<const __m256i *>(values));
   84|  4.22M|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEC2EDv4_x:
  232|  33.0M|    simdjson_inline simd8(const __m256i _value) : base8_numeric<uint8_t>(_value) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhEC2EDv4_x:
   99|  33.0M|    simdjson_inline base8_numeric(const __m256i _value) : base8<T>(_value) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5base8IhNS2_5simd8IbEEEC2EDv4_x:
   51|  33.0M|    simdjson_inline base8(const __m256i _value) : base<simd8<T>>(_value) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEC2EDv4_x:
   25|  33.0M|    simdjson_inline base(const __m256i _value) : value(_value) {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhE9reduce_orEv:
  330|  1.54M|    simdjson_inline simd8<T> reduce_or() const {
  331|  1.54M|      return this->chunks[0] | this->chunks[1];
  332|  1.54M|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEorES5_:
   32|  6.19M|    simdjson_inline Child operator|(const Child other) const { return _mm256_or_si256(*this, other); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEcvRKDv4_xEv:
   28|  69.3M|    simdjson_inline operator const __m256i&() const { return this->value; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE8is_asciiEv:
  283|  1.54M|    simdjson_inline bool is_ascii() const { return _mm256_movemask_epi8(*this) == 0; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEoRES5_:
   36|  1.55M|    simdjson_inline Child& operator|=(const Child other) { auto this_cast = static_cast<Child*>(this); *this_cast = *this_cast | other; return *this_cast; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5base8IhNS2_5simd8IbEEE4prevILi1EEENS4_IhEES8_:
   58|  12.1k|    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
   59|  12.1k|      return _mm256_alignr_epi8(*this, _mm256_permute2x128_si256(prev_chunk, *this, 0x21), 16 - N);
   60|  12.1k|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE3shrILi4EEES4_v:
  289|  24.2k|    simdjson_inline simd8<uint8_t> shr() const { return simd8<uint8_t>(_mm256_srli_epi16(*this, N)) & uint8_t(0xFFu >> N); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhE9lookup_16IhEENS2_5simd8IT_EES7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_S7_:
  177|  36.3k|        L replace12, L replace13, L replace14, L replace15) const {
  178|  36.3k|      return lookup_16(simd8<L>::repeat_16(
  179|  36.3k|        replace0,  replace1,  replace2,  replace3,
  180|  36.3k|        replace4,  replace5,  replace6,  replace7,
  181|  36.3k|        replace8,  replace9,  replace10, replace11,
  182|  36.3k|        replace12, replace13, replace14, replace15
  183|  36.3k|      ));
  184|  36.3k|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhE9lookup_16IhEENS2_5simd8IT_EES8_:
  115|  36.3k|    simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
  116|  36.3k|      return _mm256_shuffle_epi8(lookup_table, *this);
  117|  36.3k|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEcvRDv4_xEv:
   29|  36.3k|    simdjson_inline operator __m256i&() { return this->value; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE9repeat_16Ehhhhhhhhhhhhhhhh:
  253|  3.11M|    ) {
  254|  3.11M|      return simd8<uint8_t>(
  255|  3.11M|        v0, v1, v2, v3, v4, v5, v6, v7,
  256|  3.11M|        v8, v9, v10,v11,v12,v13,v14,v15,
  257|  3.11M|        v0, v1, v2, v3, v4, v5, v6, v7,
  258|  3.11M|        v8, v9, v10,v11,v12,v13,v14,v15
  259|  3.11M|      );
  260|  3.11M|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEC2Ehhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:
  243|  3.11M|    ) : simd8(_mm256_setr_epi8(
  244|  3.11M|      v0, v1, v2, v3, v4, v5, v6, v7,
  245|  3.11M|      v8, v9, v10,v11,v12,v13,v14,v15,
  246|  3.11M|      v16,v17,v18,v19,v20,v21,v22,v23,
  247|  3.11M|      v24,v25,v26,v27,v28,v29,v30,v31
  248|  3.11M|    )) {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEanES5_:
   33|  72.7k|    simdjson_inline Child operator&(const Child other) const { return _mm256_and_si256(*this, other); }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEC2Eh:
  234|  5.43M|    simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhE5splatEh:
   80|  10.0M|    static simdjson_inline simd8<T> splat(T _value) { return _mm256_set1_epi8(_value); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5base8IhNS2_5simd8IbEEE4prevILi2EEENS4_IhEES8_:
   58|  12.1k|    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
   59|  12.1k|      return _mm256_alignr_epi8(*this, _mm256_permute2x128_si256(prev_chunk, *this, 0x21), 16 - N);
   60|  12.1k|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5base8IhNS2_5simd8IbEEE4prevILi3EEENS4_IhEES8_:
   58|  12.1k|    simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
   59|  12.1k|      return _mm256_alignr_epi8(*this, _mm256_permute2x128_si256(prev_chunk, *this, 0x21), 16 - N);
   60|  12.1k|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE14saturating_subES4_:
  264|  30.3k|    simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return _mm256_subs_epu8(*this, other); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IhEEEeoES5_:
   34|  12.1k|    simdjson_inline Child operator^(const Child other) const { return _mm256_xor_si256(*this, other); }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEC2EPKh:
  236|  1.14M|    simdjson_inline simd8(const uint8_t values[32]) : simd8(load(values)) {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE7gt_bitsES4_:
  270|  6.06k|    simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return this->saturating_sub(other); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE21any_bits_set_anywhereEv:
  285|  10.5k|    simdjson_inline bool any_bits_set_anywhere() const { return !bits_not_set_anywhere(); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE21bits_not_set_anywhereEv:
  284|  10.5k|    simdjson_inline bool bits_not_set_anywhere() const { return _mm256_testz_si256(*this, *this); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd13base8_numericIhE5storeEPh:
  102|  1.13M|    simdjson_inline void store(T dst[32]) const { return _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst), *this); }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simdeqENS2_5simd8IhEES4_:
   53|  17.6M|    friend simdjson_really_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return _mm256_cmpeq_epi8(lhs, rhs); }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5simd8IbEC2EDv4_x:
   69|  17.6M|    simdjson_inline simd8(const __m256i _value) : base8<bool>(_value) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd5base8IbNS2_5simd8IbEEEC2EDv4_x:
   51|  17.6M|    simdjson_inline base8(const __m256i _value) : base<simd8<T>>(_value) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IbEEEC2EDv4_x:
   25|  17.6M|    simdjson_inline base(const __m256i _value) : value(_value) {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IbE10to_bitmaskEv:
   73|  17.6M|    simdjson_inline int to_bitmask() const { return _mm256_movemask_epi8(*this); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd4baseINS2_5simd8IbEEEcvRKDv4_xEv:
   28|  17.6M|    simdjson_inline operator const __m256i&() const { return this->value; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhE2eqEh:
  342|  3.08M|    simdjson_inline uint64_t eq(const T m) const {
  343|  3.08M|      const simd8<T> mask = simd8<T>::splat(m);
  344|  3.08M|      return  simd8x64<bool>(
  345|  3.08M|        this->chunks[0] == mask,
  346|  3.08M|        this->chunks[1] == mask
  347|  3.08M|      ).to_bitmask();
  348|  3.08M|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IbEC2ENS2_5simd8IbEES6_:
  308|  7.70M|    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IbE10to_bitmaskEv:
  324|  7.70M|    simdjson_inline uint64_t to_bitmask() const {
  325|  7.70M|      uint64_t r_lo = uint32_t(this->chunks[0].to_bitmask());
  326|  7.70M|      uint64_t r_hi =                       this->chunks[1].to_bitmask();
  327|  7.70M|      return r_lo | (r_hi << 32);
  328|  7.70M|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhE2eqERKS4_:
  350|  3.08M|    simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
  351|  3.08M|      return  simd8x64<bool>(
  352|  3.08M|        this->chunks[0] == other.chunks[0],
  353|  3.08M|        this->chunks[1] == other.chunks[1]
  354|  3.08M|      ).to_bitmask();
  355|  3.08M|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhEC2ENS2_5simd8IhEES6_:
  308|  4.62M|    simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd8simd8x64IhE4lteqEh:
  357|  1.54M|    simdjson_inline uint64_t lteq(const T m) const {
  358|  1.54M|      const simd8<T> mask = simd8<T>::splat(m);
  359|  1.54M|      return  simd8x64<bool>(
  360|  1.54M|        this->chunks[0] <= mask,
  361|  1.54M|        this->chunks[1] <= mask
  362|  1.54M|      ).to_bitmask();
  363|  1.54M|    }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhEleES4_:
  273|  3.08M|    simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return other.max_val(*this) == other; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_14simd5simd8IhE7max_valES4_:
  267|  3.08M|    simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> other) const { return _mm256_max_epu8(*this, other); }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_119backslash_and_quote13copy_and_findEPKhPh:
   31|  1.13M|simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
   32|       |  // this can read up to 15 bytes beyond the buffer size, but we require
   33|       |  // SIMDJSON_PADDING of padding
   34|  1.13M|  static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
   35|  1.13M|  simd8<uint8_t> v(src);
   36|       |  // store to dest unconditionally - we can overwrite the bits we don't like later
   37|  1.13M|  v.store(dst);
   38|  1.13M|  return {
   39|  1.13M|      static_cast<uint32_t>((v == '\\').to_bitmask()),     // bs_bits
   40|  1.13M|      static_cast<uint32_t>((v == '"').to_bitmask()), // quote_bits
   41|  1.13M|  };
   42|  1.13M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_119backslash_and_quote15has_quote_firstEv:
   22|  1.13M|  simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_119backslash_and_quote11quote_indexEv:
   24|   250k|  simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_119backslash_and_quote13has_backslashEv:
   23|   887k|  simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_119backslash_and_quote15backslash_indexEv:
   25|  43.9k|  simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }

_ZN8simdjson7icelake14implementationC2Ev:
   19|      1|  simdjson_inline implementation() : simdjson::implementation(
   20|      1|      "icelake",
   21|      1|      "Intel/AMD AVX512",
   22|      1|      internal::instruction_set::AVX2 | internal::instruction_set::PCLMULQDQ | internal::instruction_set::BMI1 | internal::instruction_set::BMI2 | internal::instruction_set::AVX512F | internal::instruction_set::AVX512DQ | internal::instruction_set::AVX512CD | internal::instruction_set::AVX512BW | internal::instruction_set::AVX512VL | internal::instruction_set::AVX512VBMI2
   23|      1|  ) {}

_ZNK8simdjson14implementation25required_instruction_setsEv:
   84|      2|  virtual uint32_t required_instruction_sets() const { return _required_instruction_sets; }
_ZN8simdjson14implementationC2ENSt3__117basic_string_viewIcNS1_11char_traitsIcEEEES5_j:
  137|      5|    _name(name),
  138|      5|    _description(description),
  139|      5|    _required_instruction_sets(required_instruction_sets)
  140|      5|  {
  141|      5|  }
_ZN8simdjson8internal29available_implementation_listC2Ev:
  171|      1|  simdjson_inline available_implementation_list() {}

_ZN8simdjson8internal10atomic_ptrIKNS_14implementationEEptEv:
   21|  10.8k|  T* operator->() { return ptr.load(); }
_ZN8simdjson8internal10atomic_ptrIKNS_14implementationEEaSEPS3_:
   22|      1|  atomic_ptr& operator=(T *_ptr) { ptr = _ptr; return *this; }
_ZN8simdjson8internal10atomic_ptrIKNS_14implementationEEcvPS3_Ev:
   19|      1|  operator T*() { return ptr.load(); }
_ZN8simdjson8internal10atomic_ptrIKNS_14implementationEEC2EPS3_:
   13|      1|  atomic_ptr(T *_ptr) : ptr{_ptr} {}

_ZNK8simdjson8internal25dom_parser_implementation8capacityEv:
  228|  10.8k|simdjson_pure simdjson_inline size_t dom_parser_implementation::capacity() const noexcept {
  229|  10.8k|  return _capacity;
  230|  10.8k|}
_ZNK8simdjson8internal25dom_parser_implementation9max_depthEv:
  232|  89.3k|simdjson_pure simdjson_inline size_t dom_parser_implementation::max_depth() const noexcept {
  233|  89.3k|  return _max_depth;
  234|  89.3k|}
_ZN8simdjson12is_streamingENS_11stage1_modeE:
   27|  21.7k|inline bool is_streaming(stage1_mode mode) {
   28|       |  // performance note: it is probably faster to check that mode is different
   29|       |  // from regular than checking that it is either streaming_partial or streaming_final.
   30|  21.7k|  return (mode != stage1_mode::regular);
   31|       |  // return (mode == stage1_mode::streaming_partial || mode == stage1_mode::streaming_final);
   32|  21.7k|}
_ZN8simdjson8internal25dom_parser_implementationC2Ev:
  224|  10.8k|simdjson_inline dom_parser_implementation::dom_parser_implementation() noexcept = default;
_ZN8simdjson8internal25dom_parser_implementationD2Ev:
  166|  10.8k|  virtual ~dom_parser_implementation() = default;

_ZN8simdjson8internal8tape_refC2Ev:
   19|  15.1k|simdjson_inline tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
_ZN8simdjson8internal8tape_refC2EPKNS_3dom8documentEm:
   20|   181k|simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
_ZNK8simdjson8internal8tape_ref15get_string_viewEv:
  108|   243k|inline std::string_view internal::tape_ref::get_string_view() const noexcept {
  109|   243k|  return std::string_view(
  110|   243k|      get_c_str(),
  111|   243k|      get_string_length()
  112|   243k|  );
  113|   243k|}
_ZNK8simdjson8internal8tape_ref9get_c_strEv:
  103|   243k|simdjson_inline const char * internal::tape_ref::get_c_str() const noexcept {
  104|   243k|  size_t string_buf_index = size_t(tape_value());
  105|   243k|  return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
  106|   243k|}
_ZNK8simdjson8internal8tape_ref10tape_valueEv:
   74|   487k|simdjson_inline uint64_t internal::tape_ref::tape_value() const noexcept {
   75|   487k|  return doc->tape[json_index] & internal::JSON_VALUE_MASK;
   76|   487k|}
_ZNK8simdjson8internal8tape_ref17get_string_lengthEv:
   96|   243k|simdjson_inline uint32_t internal::tape_ref::get_string_length() const noexcept {
   97|   243k|  size_t string_buf_index = size_t(tape_value());
   98|   243k|  uint32_t len;
   99|   243k|  std::memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
  100|   243k|  return len;
  101|   243k|}
_ZNK8simdjson8internal8tape_ref13tape_ref_typeEv:
   71|  13.8M|simdjson_inline tape_type tape_ref::tape_ref_type() const noexcept {
   72|  13.8M|  return static_cast<tape_type>(doc->tape[json_index] >> 56);
   73|  13.8M|}
_ZNK8simdjson8internal8tape_ref13after_elementEv:
   58|  1.79M|inline size_t tape_ref::after_element() const noexcept {
   59|  1.79M|  switch (tape_ref_type()) {
   60|  14.1k|    case tape_type::START_ARRAY:
  ------------------
  |  Branch (60:5): [True: 14.1k, False: 1.78M]
  ------------------
   61|  21.6k|    case tape_type::START_OBJECT:
  ------------------
  |  Branch (61:5): [True: 7.59k, False: 1.79M]
  ------------------
   62|  21.6k|      return matching_brace_index();
   63|    868|    case tape_type::UINT64:
  ------------------
  |  Branch (63:5): [True: 868, False: 1.79M]
  ------------------
   64|   664k|    case tape_type::INT64:
  ------------------
  |  Branch (64:5): [True: 663k, False: 1.13M]
  ------------------
   65|  1.77M|    case tape_type::DOUBLE:
  ------------------
  |  Branch (65:5): [True: 1.11M, False: 687k]
  ------------------
   66|  1.77M|      return json_index + 2;
   67|  1.41k|    default:
  ------------------
  |  Branch (67:5): [True: 1.41k, False: 1.79M]
  ------------------
   68|  1.41k|      return json_index + 1;
   69|  1.79M|  }
   70|  1.79M|}
_ZNK8simdjson8internal8tape_ref20matching_brace_indexEv:
   77|  35.5k|simdjson_inline uint32_t internal::tape_ref::matching_brace_index() const noexcept {
   78|  35.5k|  return uint32_t(doc->tape[json_index]);
   79|  35.5k|}
_ZNK8simdjson8internal8tape_ref15next_tape_valueIlEET_v:
   85|  2.32M|simdjson_inline T tape_ref::next_tape_value() const noexcept {
   86|  2.32M|  static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
   87|       |  // Though the following is tempting...
   88|       |  //  return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
   89|       |  // It is not generally safe. It is safer, and often faster to rely
   90|       |  // on memcpy. Yes, it is uglier, but it is also encapsulated.
   91|  2.32M|  T x;
   92|  2.32M|  std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
   93|  2.32M|  return x;
   94|  2.32M|}
_ZNK8simdjson8internal8tape_ref15next_tape_valueImEET_v:
   85|  1.88k|simdjson_inline T tape_ref::next_tape_value() const noexcept {
   86|  1.88k|  static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
   87|       |  // Though the following is tempting...
   88|       |  //  return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
   89|       |  // It is not generally safe. It is safer, and often faster to rely
   90|       |  // on memcpy. Yes, it is uglier, but it is also encapsulated.
   91|  1.88k|  T x;
   92|  1.88k|  std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
   93|  1.88k|  return x;
   94|  1.88k|}
_ZNK8simdjson8internal8tape_ref15next_tape_valueIdEET_v:
   85|  2.77M|simdjson_inline T tape_ref::next_tape_value() const noexcept {
   86|  2.77M|  static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
   87|       |  // Though the following is tempting...
   88|       |  //  return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
   89|       |  // It is not generally safe. It is safer, and often faster to rely
   90|       |  // on memcpy. Yes, it is uglier, but it is also encapsulated.
   91|  2.77M|  T x;
   92|  2.77M|  std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
   93|  2.77M|  return x;
   94|  2.77M|}

_ZN8simdjson8internal22allocate_padded_bufferEm:
   21|  10.8k|inline char *allocate_padded_buffer(size_t length) noexcept {
   22|  10.8k|  const size_t totalpaddedlength = length + SIMDJSON_PADDING;
   23|  10.8k|  if(totalpaddedlength<length) {
  ------------------
  |  Branch (23:6): [True: 0, False: 10.8k]
  ------------------
   24|       |    // overflow
   25|      0|    return nullptr;
   26|      0|  }
   27|  10.8k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
   28|       |  // avoid getting out of memory
   29|  10.8k|  if (totalpaddedlength>(1UL<<20)) {
  ------------------
  |  Branch (29:7): [True: 9, False: 10.8k]
  ------------------
   30|      9|    return nullptr;
   31|      9|  }
   32|  10.8k|#endif
   33|       |
   34|  10.8k|  char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
   35|  10.8k|  if (padded_buffer == nullptr) {
  ------------------
  |  Branch (35:7): [True: 0, False: 10.8k]
  ------------------
   36|      0|    return nullptr;
   37|      0|  }
   38|       |  // We write nulls in the padded region to avoid having uninitialized
   39|       |  // content which may trigger warning for some sanitizers
   40|  10.8k|  std::memset(padded_buffer + length, 0, totalpaddedlength - length);
   41|  10.8k|  return padded_buffer;
   42|  10.8k|} // allocate_padded_buffer()

_ZN8simdjson8westmere14implementationC2Ev:
   19|      1|  simdjson_inline implementation() : simdjson::implementation("westmere", "Intel/AMD SSE4.2", internal::instruction_set::SSE42 | internal::instruction_set::PCLMULQDQ) {}

_ZN8simdjson8internal10is_integerEc:
   67|  15.0M|bool is_integer(char c)  noexcept  { return (c >= '0' && c <= '9'); }
  ------------------
  |  Branch (67:46): [True: 15.0M, False: 13.2k]
  |  Branch (67:58): [True: 15.0M, False: 2.37k]
  ------------------
_ZN8simdjson8internal13parse_decimalERPKc:
   70|  7.30k|decimal parse_decimal(const char *&p) noexcept {
   71|  7.30k|  decimal answer;
   72|  7.30k|  answer.num_digits = 0;
   73|  7.30k|  answer.decimal_point = 0;
   74|  7.30k|  answer.truncated = false;
   75|  7.30k|  answer.negative = (*p == '-');
   76|  7.30k|  if ((*p == '-') || (*p == '+')) {
  ------------------
  |  Branch (76:7): [True: 0, False: 7.30k]
  |  Branch (76:22): [True: 0, False: 7.30k]
  ------------------
   77|      0|    ++p;
   78|      0|  }
   79|       |
   80|  8.49k|  while (*p == '0') {
  ------------------
  |  Branch (80:10): [True: 1.18k, False: 7.30k]
  ------------------
   81|  1.18k|    ++p;
   82|  1.18k|  }
   83|  11.3M|  while (is_integer(*p)) {
  ------------------
  |  Branch (83:10): [True: 11.3M, False: 7.30k]
  ------------------
   84|  11.3M|    if (answer.num_digits < max_digits) {
  ------------------
  |  Branch (84:9): [True: 131k, False: 11.2M]
  ------------------
   85|   131k|      answer.digits[answer.num_digits] = uint8_t(*p - '0');
   86|   131k|    }
   87|  11.3M|    answer.num_digits++;
   88|  11.3M|    ++p;
   89|  11.3M|  }
   90|  7.30k|  if (*p == '.') {
  ------------------
  |  Branch (90:7): [True: 6.15k, False: 1.14k]
  ------------------
   91|  6.15k|    ++p;
   92|  6.15k|    const char *first_after_period = p;
   93|       |    // if we have not yet encountered a zero, we have to skip it as well
   94|  6.15k|    if (answer.num_digits == 0) {
  ------------------
  |  Branch (94:9): [True: 1.18k, False: 4.97k]
  ------------------
   95|       |      // skip zeros
   96|   267k|      while (*p == '0') {
  ------------------
  |  Branch (96:14): [True: 266k, False: 1.18k]
  ------------------
   97|   266k|        ++p;
   98|   266k|      }
   99|  1.18k|    }
  100|  3.27M|    while (is_integer(*p)) {
  ------------------
  |  Branch (100:12): [True: 3.26M, False: 6.15k]
  ------------------
  101|  3.26M|      if (answer.num_digits < max_digits) {
  ------------------
  |  Branch (101:11): [True: 389k, False: 2.87M]
  ------------------
  102|   389k|        answer.digits[answer.num_digits] = uint8_t(*p - '0');
  103|   389k|      }
  104|  3.26M|      answer.num_digits++;
  105|  3.26M|      ++p;
  106|  3.26M|    }
  107|  6.15k|    answer.decimal_point = int32_t(first_after_period - p);
  108|  6.15k|  }
  109|  7.30k|  if(answer.num_digits > 0) {
  ------------------
  |  Branch (109:6): [True: 7.22k, False: 77]
  ------------------
  110|  7.22k|    const char *preverse = p - 1;
  111|  7.22k|    int32_t trailing_zeros = 0;
  112|   421k|    while ((*preverse == '0') || (*preverse == '.')) {
  ------------------
  |  Branch (112:12): [True: 413k, False: 7.99k]
  |  Branch (112:34): [True: 770, False: 7.22k]
  ------------------
  113|   414k|      if(*preverse == '0') { trailing_zeros++; };
  ------------------
  |  Branch (113:10): [True: 413k, False: 770]
  ------------------
  114|   414k|      --preverse;
  115|   414k|    }
  116|  7.22k|    answer.decimal_point += int32_t(answer.num_digits);
  117|  7.22k|    answer.num_digits -= uint32_t(trailing_zeros);
  118|  7.22k|  }
  119|  7.30k|  if(answer.num_digits > max_digits ) {
  ------------------
  |  Branch (119:6): [True: 441, False: 6.86k]
  ------------------
  120|    441|    answer.num_digits = max_digits;
  121|    441|    answer.truncated = true;
  122|    441|  }
  123|  7.30k|  if (('e' == *p) || ('E' == *p)) {
  ------------------
  |  Branch (123:7): [True: 1.03k, False: 6.26k]
  |  Branch (123:22): [True: 1.07k, False: 5.18k]
  ------------------
  124|  2.11k|    ++p;
  125|  2.11k|    bool neg_exp = false;
  126|  2.11k|    if ('-' == *p) {
  ------------------
  |  Branch (126:9): [True: 950, False: 1.16k]
  ------------------
  127|    950|      neg_exp = true;
  128|    950|      ++p;
  129|  1.16k|    } else if ('+' == *p) {
  ------------------
  |  Branch (129:16): [True: 196, False: 972]
  ------------------
  130|    196|      ++p;
  131|    196|    }
  132|  2.11k|    int32_t exp_number = 0; // exponential part
  133|   400k|    while (is_integer(*p)) {
  ------------------
  |  Branch (133:12): [True: 398k, False: 2.11k]
  ------------------
  134|   398k|      uint8_t digit = uint8_t(*p - '0');
  135|   398k|      if (exp_number < 0x10000) {
  ------------------
  |  Branch (135:11): [True: 4.99k, False: 393k]
  ------------------
  136|  4.99k|        exp_number = 10 * exp_number + digit;
  137|  4.99k|      }
  138|   398k|      ++p;
  139|   398k|    }
  140|  2.11k|    answer.decimal_point += (neg_exp ? -exp_number : exp_number);
  ------------------
  |  Branch (140:30): [True: 950, False: 1.16k]
  ------------------
  141|  2.11k|  }
  142|  7.30k|  return answer;
  143|  7.30k|}
_ZN8simdjson8internal5roundERNS0_7decimalE:
  331|  8.23k|uint64_t round(decimal &h) {
  332|  8.23k|  if ((h.num_digits == 0) || (h.decimal_point < 0)) {
  ------------------
  |  Branch (332:7): [True: 0, False: 8.23k]
  |  Branch (332:30): [True: 200, False: 8.03k]
  ------------------
  333|    200|    return 0;
  334|  8.03k|  } else if (h.decimal_point > 18) {
  ------------------
  |  Branch (334:14): [True: 0, False: 8.03k]
  ------------------
  335|      0|    return UINT64_MAX;
  336|      0|  }
  337|       |  // at this point, we know that h.decimal_point >= 0
  338|  8.03k|  uint32_t dp = uint32_t(h.decimal_point);
  339|  8.03k|  uint64_t n = 0;
  340|   133k|  for (uint32_t i = 0; i < dp; i++) {
  ------------------
  |  Branch (340:24): [True: 125k, False: 8.03k]
  ------------------
  341|   125k|    n = (10 * n) + ((i < h.num_digits) ? h.digits[i] : 0);
  ------------------
  |  Branch (341:21): [True: 124k, False: 556]
  ------------------
  342|   125k|  }
  343|  8.03k|  bool round_up = false;
  344|  8.03k|  if (dp < h.num_digits) {
  ------------------
  |  Branch (344:7): [True: 7.58k, False: 454]
  ------------------
  345|  7.58k|    round_up = h.digits[dp] >= 5; // normally, we round up
  346|       |    // but we may need to round to even!
  347|  7.58k|    if ((h.digits[dp] == 5) && (dp + 1 == h.num_digits)) {
  ------------------
  |  Branch (347:9): [True: 1.10k, False: 6.47k]
  |  Branch (347:32): [True: 485, False: 623]
  ------------------
  348|    485|      round_up = h.truncated || ((dp > 0) && (1 & h.digits[dp - 1]));
  ------------------
  |  Branch (348:18): [True: 269, False: 216]
  |  Branch (348:34): [True: 216, False: 0]
  |  Branch (348:46): [True: 26, False: 190]
  ------------------
  349|    485|    }
  350|  7.58k|  }
  351|  8.03k|  if (round_up) {
  ------------------
  |  Branch (351:7): [True: 5.87k, False: 2.16k]
  ------------------
  352|  5.87k|    n++;
  353|  5.87k|  }
  354|  8.03k|  return n;
  355|  8.23k|}
_ZN8simdjson8internal18decimal_left_shiftERNS0_7decimalEj:
  358|  25.3k|void decimal_left_shift(decimal &h, uint32_t shift) {
  359|  25.3k|  if (h.num_digits == 0) {
  ------------------
  |  Branch (359:7): [True: 0, False: 25.3k]
  ------------------
  360|      0|    return;
  361|      0|  }
  362|  25.3k|  uint32_t num_new_digits = number_of_digits_decimal_left_shift(h, shift);
  363|  25.3k|  int32_t read_index = int32_t(h.num_digits - 1);
  364|  25.3k|  uint32_t write_index = h.num_digits - 1 + num_new_digits;
  365|  25.3k|  uint64_t n = 0;
  366|       |
  367|  2.92M|  while (read_index >= 0) {
  ------------------
  |  Branch (367:10): [True: 2.89M, False: 25.3k]
  ------------------
  368|  2.89M|    n += uint64_t(h.digits[read_index]) << shift;
  369|  2.89M|    uint64_t quotient = n / 10;
  370|  2.89M|    uint64_t remainder = n - (10 * quotient);
  371|  2.89M|    if (write_index < max_digits) {
  ------------------
  |  Branch (371:9): [True: 2.89M, False: 4.25k]
  ------------------
  372|  2.89M|      h.digits[write_index] = uint8_t(remainder);
  373|  2.89M|    } else if (remainder > 0) {
  ------------------
  |  Branch (373:16): [True: 3.56k, False: 688]
  ------------------
  374|  3.56k|      h.truncated = true;
  375|  3.56k|    }
  376|  2.89M|    n = quotient;
  377|  2.89M|    write_index--;
  378|  2.89M|    read_index--;
  379|  2.89M|  }
  380|   297k|  while (n > 0) {
  ------------------
  |  Branch (380:10): [True: 271k, False: 25.3k]
  ------------------
  381|   271k|    uint64_t quotient = n / 10;
  382|   271k|    uint64_t remainder = n - (10 * quotient);
  383|   271k|    if (write_index < max_digits) {
  ------------------
  |  Branch (383:9): [True: 271k, False: 0]
  ------------------
  384|   271k|      h.digits[write_index] = uint8_t(remainder);
  385|   271k|    } else if (remainder > 0) {
  ------------------
  |  Branch (385:16): [True: 0, False: 0]
  ------------------
  386|      0|      h.truncated = true;
  387|      0|    }
  388|   271k|    n = quotient;
  389|   271k|    write_index--;
  390|   271k|  }
  391|  25.3k|  h.num_digits += num_new_digits;
  392|  25.3k|  if (h.num_digits > max_digits) {
  ------------------
  |  Branch (392:7): [True: 302, False: 25.0k]
  ------------------
  393|    302|    h.num_digits = max_digits;
  394|    302|  }
  395|  25.3k|  h.decimal_point += int32_t(num_new_digits);
  396|  25.3k|  trim(h);
  397|  25.3k|}
_ZN8simdjson8internal19decimal_right_shiftERNS0_7decimalEj:
  400|  14.2k|void decimal_right_shift(decimal &h, uint32_t shift) {
  401|  14.2k|  uint32_t read_index = 0;
  402|  14.2k|  uint32_t write_index = 0;
  403|       |
  404|  14.2k|  uint64_t n = 0;
  405|       |
  406|   170k|  while ((n >> shift) == 0) {
  ------------------
  |  Branch (406:10): [True: 156k, False: 13.2k]
  ------------------
  407|   156k|    if (read_index < h.num_digits) {
  ------------------
  |  Branch (407:9): [True: 155k, False: 1.00k]
  ------------------
  408|   155k|      n = (10 * n) + h.digits[read_index++];
  409|   155k|    } else if (n == 0) {
  ------------------
  |  Branch (409:16): [True: 0, False: 1.00k]
  ------------------
  410|      0|      return;
  411|  1.00k|    } else {
  412|  5.94k|      while ((n >> shift) == 0) {
  ------------------
  |  Branch (412:14): [True: 4.94k, False: 1.00k]
  ------------------
  413|  4.94k|        n = 10 * n;
  414|  4.94k|        read_index++;
  415|  4.94k|      }
  416|  1.00k|      break;
  417|  1.00k|    }
  418|   156k|  }
  419|  14.2k|  h.decimal_point -= int32_t(read_index - 1);
  420|  14.2k|  if (h.decimal_point < -decimal_point_range) { // it is zero
  ------------------
  |  Branch (420:7): [True: 0, False: 14.2k]
  ------------------
  421|      0|    h.num_digits = 0;
  422|      0|    h.decimal_point = 0;
  423|      0|    h.negative = false;
  424|      0|    h.truncated = false;
  425|      0|    return;
  426|      0|  }
  427|  14.2k|  uint64_t mask = (uint64_t(1) << shift) - 1;
  428|  2.71M|  while (read_index < h.num_digits) {
  ------------------
  |  Branch (428:10): [True: 2.70M, False: 14.2k]
  ------------------
  429|  2.70M|    uint8_t new_digit = uint8_t(n >> shift);
  430|  2.70M|    n = (10 * (n & mask)) + h.digits[read_index++];
  431|  2.70M|    h.digits[write_index++] = new_digit;
  432|  2.70M|  }
  433|   463k|  while (n > 0) {
  ------------------
  |  Branch (433:10): [True: 449k, False: 14.2k]
  ------------------
  434|   449k|    uint8_t new_digit = uint8_t(n >> shift);
  435|   449k|    n = 10 * (n & mask);
  436|   449k|    if (write_index < max_digits) {
  ------------------
  |  Branch (436:9): [True: 444k, False: 4.68k]
  ------------------
  437|   444k|      h.digits[write_index++] = new_digit;
  438|   444k|    } else if (new_digit > 0) {
  ------------------
  |  Branch (438:16): [True: 4.18k, False: 496]
  ------------------
  439|  4.18k|      h.truncated = true;
  440|  4.18k|    }
  441|   449k|  }
  442|  14.2k|  h.num_digits = write_index;
  443|  14.2k|  trim(h);
  444|  14.2k|}
_ZN8simdjson8internal10from_charsEPKc:
  570|  7.30k|double from_chars(const char *first) noexcept {
  571|  7.30k|  bool negative = first[0] == '-';
  572|  7.30k|  if (negative) {
  ------------------
  |  Branch (572:7): [True: 206, False: 7.10k]
  ------------------
  573|    206|    first++;
  574|    206|  }
  575|  7.30k|  adjusted_mantissa am = parse_long_mantissa<binary_format<double>>(first);
  576|  7.30k|  uint64_t word = am.mantissa;
  577|  7.30k|  word |= uint64_t(am.power2)
  578|  7.30k|          << binary_format<double>::mantissa_explicit_bits();
  579|  7.30k|  word = negative ? word | (uint64_t(1) << binary_format<double>::sign_index())
  ------------------
  |  Branch (579:10): [True: 206, False: 7.10k]
  ------------------
  580|  7.30k|                  : word;
  581|  7.30k|  double value;
  582|  7.30k|  std::memcpy(&value, &word, sizeof(double));
  583|  7.30k|  return value;
  584|  7.30k|}
simdjson.cpp:_ZN8simdjson8internal12_GLOBAL__N_135number_of_digits_decimal_left_shiftERNS0_7decimalEj:
  234|  25.3k|uint32_t number_of_digits_decimal_left_shift(decimal &h, uint32_t shift) {
  235|  25.3k|  shift &= 63;
  236|  25.3k|  const static uint16_t number_of_digits_decimal_left_shift_table[65] = {
  237|  25.3k|      0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817,
  238|  25.3k|      0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067,
  239|  25.3k|      0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF,
  240|  25.3k|      0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0,
  241|  25.3k|      0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA,
  242|  25.3k|      0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC,
  243|  25.3k|      0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C,
  244|  25.3k|      0x051C, 0x051C,
  245|  25.3k|  };
  246|  25.3k|  uint32_t x_a = number_of_digits_decimal_left_shift_table[shift];
  247|  25.3k|  uint32_t x_b = number_of_digits_decimal_left_shift_table[shift + 1];
  248|  25.3k|  uint32_t num_new_digits = x_a >> 11;
  249|  25.3k|  uint32_t pow5_a = 0x7FF & x_a;
  250|  25.3k|  uint32_t pow5_b = 0x7FF & x_b;
  251|  25.3k|  const static uint8_t
  252|  25.3k|      number_of_digits_decimal_left_shift_table_powers_of_5[0x051C] = {
  253|  25.3k|          5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5,
  254|  25.3k|          3, 9, 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8,
  255|  25.3k|          2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2,
  256|  25.3k|          5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1,
  257|  25.3k|          5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5,
  258|  25.3k|          3, 8, 1, 4, 6, 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2,
  259|  25.3k|          8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3,
  260|  25.3k|          7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9, 1, 0, 1, 5,
  261|  25.3k|          6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6,
  262|  25.3k|          0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3,
  263|  25.3k|          8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7,
  264|  25.3k|          6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, 2,
  265|  25.3k|          5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8,
  266|  25.3k|          6, 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3,
  267|  25.3k|          2, 2, 5, 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1,
  268|  25.3k|          2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6,
  269|  25.3k|          4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3,
  270|  25.3k|          2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6,
  271|  25.3k|          6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3,
  272|  25.3k|          8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, 1, 3, 2, 8, 1, 2, 5, 1, 4, 5,
  273|  25.3k|          5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0, 6, 2, 5,
  274|  25.3k|          7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3,
  275|  25.3k|          1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6,
  276|  25.3k|          6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6,
  277|  25.3k|          4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7,
  278|  25.3k|          2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7,
  279|  25.3k|          3, 5, 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5,
  280|  25.3k|          2, 2, 7, 3, 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5,
  281|  25.3k|          9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0,
  282|  25.3k|          2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
  283|  25.3k|          8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5,
  284|  25.3k|          2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4,
  285|  25.3k|          9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, 8, 5, 4, 7, 1, 5, 2, 0, 2,
  286|  25.3k|          0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1, 0, 5,
  287|  25.3k|          4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7,
  288|  25.3k|          5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9,
  289|  25.3k|          2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5,
  290|  25.3k|          6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9,
  291|  25.3k|          4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3,
  292|  25.3k|          2, 3, 3, 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8,
  293|  25.3k|          9, 2, 0, 9, 8, 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2,
  294|  25.3k|          3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1,
  295|  25.3k|          3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1,
  296|  25.3k|          1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3,
  297|  25.3k|          1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2,
  298|  25.3k|          3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, 4, 1,
  299|  25.3k|          0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1, 3,
  300|  25.3k|          5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1,
  301|  25.3k|          3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3,
  302|  25.3k|          9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3,
  303|  25.3k|          9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6,
  304|  25.3k|          7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3,
  305|  25.3k|          6, 1, 4, 1, 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7,
  306|  25.3k|          6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9,
  307|  25.3k|          4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2,
  308|  25.3k|          5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9,
  309|  25.3k|          6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
  310|  25.3k|      };
  311|  25.3k|  const uint8_t *pow5 =
  312|  25.3k|      &number_of_digits_decimal_left_shift_table_powers_of_5[pow5_a];
  313|  25.3k|  uint32_t i = 0;
  314|  25.3k|  uint32_t n = pow5_b - pow5_a;
  315|  27.3k|  for (; i < n; i++) {
  ------------------
  |  Branch (315:10): [True: 27.1k, False: 200]
  ------------------
  316|  27.1k|    if (i >= h.num_digits) {
  ------------------
  |  Branch (316:9): [True: 588, False: 26.6k]
  ------------------
  317|    588|      return num_new_digits - 1;
  318|  26.6k|    } else if (h.digits[i] == pow5[i]) {
  ------------------
  |  Branch (318:16): [True: 1.99k, False: 24.6k]
  ------------------
  319|  1.99k|      continue;
  320|  24.6k|    } else if (h.digits[i] < pow5[i]) {
  ------------------
  |  Branch (320:16): [True: 15.8k, False: 8.73k]
  ------------------
  321|  15.8k|      return num_new_digits - 1;
  322|  15.8k|    } else {
  323|  8.73k|      return num_new_digits;
  324|  8.73k|    }
  325|  27.1k|  }
  326|    200|  return num_new_digits;
  327|  25.3k|}
simdjson.cpp:_ZN8simdjson8internal12_GLOBAL__N_14trimERNS0_7decimalE:
  228|  39.6k|inline void trim(decimal &h) {
  229|   391k|  while ((h.num_digits > 0) && (h.digits[h.num_digits - 1] == 0)) {
  ------------------
  |  Branch (229:10): [True: 391k, False: 0]
  |  Branch (229:32): [True: 351k, False: 39.6k]
  ------------------
  230|   351k|    h.num_digits--;
  231|   351k|  }
  232|  39.6k|}
_ZN8simdjson8internal13binary_formatIdE22mantissa_explicit_bitsEv:
   54|  20.6k|template <> constexpr int binary_format<double>::mantissa_explicit_bits() {
   55|  20.6k|  return 52;
   56|  20.6k|}
_ZN8simdjson8internal13binary_formatIdE10sign_indexEv:
   65|    206|template <> constexpr int binary_format<double>::sign_index() { return 63; }
_ZN8simdjson8internal19parse_long_mantissaINS0_13binary_formatIdEEEENS0_17adjusted_mantissaEPKc:
  559|  7.30k|adjusted_mantissa parse_long_mantissa(const char *first) {
  560|  7.30k|  decimal d = parse_decimal(first);
  561|  7.30k|  return compute_float<binary>(d);
  562|  7.30k|}
_ZN8simdjson8internal13compute_floatINS0_13binary_formatIdEEEENS0_17adjusted_mantissaERNS0_7decimalE:
  446|  7.30k|template <typename binary> adjusted_mantissa compute_float(decimal &d) {
  447|  7.30k|  adjusted_mantissa answer;
  448|  7.30k|  if (d.num_digits == 0) {
  ------------------
  |  Branch (448:7): [True: 77, False: 7.22k]
  ------------------
  449|       |    // should be zero
  450|     77|    answer.power2 = 0;
  451|     77|    answer.mantissa = 0;
  452|     77|    return answer;
  453|     77|  }
  454|       |  // At this point, going further, we can assume that d.num_digits > 0.
  455|       |  // We want to guard against excessive decimal point values because
  456|       |  // they can result in long running times. Indeed, we do
  457|       |  // shifts by at most 60 bits. We have that log(10**400)/log(2**60) ~= 22
  458|       |  // which is fine, but log(10**299995)/log(2**60) ~= 16609 which is not
  459|       |  // fine (runs for a long time).
  460|       |  //
  461|  7.22k|  if(d.decimal_point < -324) {
  ------------------
  |  Branch (461:6): [True: 226, False: 7.00k]
  ------------------
  462|       |    // We have something smaller than 1e-324 which is always zero
  463|       |    // in binary64 and binary32.
  464|       |    // It should be zero.
  465|    226|    answer.power2 = 0;
  466|    226|    answer.mantissa = 0;
  467|    226|    return answer;
  468|  7.00k|  } else if(d.decimal_point >= 310) {
  ------------------
  |  Branch (468:13): [True: 154, False: 6.84k]
  ------------------
  469|       |    // We have something at least as large as 0.1e310 which is
  470|       |    // always infinite.
  471|    154|    answer.power2 = binary::infinite_power();
  472|    154|    answer.mantissa = 0;
  473|    154|    return answer;
  474|    154|  }
  475|       |
  476|  6.84k|  static const uint32_t max_shift = 60;
  477|  6.84k|  static const uint32_t num_powers = 19;
  478|  6.84k|  static const uint8_t powers[19] = {
  479|  6.84k|      0,  3,  6,  9,  13, 16, 19, 23, 26, 29, //
  480|  6.84k|      33, 36, 39, 43, 46, 49, 53, 56, 59,     //
  481|  6.84k|  };
  482|  6.84k|  int32_t exp2 = 0;
  483|  19.0k|  while (d.decimal_point > 0) {
  ------------------
  |  Branch (483:10): [True: 12.1k, False: 6.84k]
  ------------------
  484|  12.1k|    uint32_t n = uint32_t(d.decimal_point);
  485|  12.1k|    uint32_t shift = (n < num_powers) ? powers[n] : max_shift;
  ------------------
  |  Branch (485:22): [True: 6.05k, False: 6.11k]
  ------------------
  486|  12.1k|    decimal_right_shift(d, shift);
  487|  12.1k|    if (d.decimal_point < -decimal_point_range) {
  ------------------
  |  Branch (487:9): [True: 0, False: 12.1k]
  ------------------
  488|       |      // should be zero
  489|      0|      answer.power2 = 0;
  490|      0|      answer.mantissa = 0;
  491|      0|      return answer;
  492|      0|    }
  493|  12.1k|    exp2 += int32_t(shift);
  494|  12.1k|  }
  495|       |  // We shift left toward [1/2 ... 1].
  496|  25.5k|  while (d.decimal_point <= 0) {
  ------------------
  |  Branch (496:10): [True: 25.5k, False: 0]
  ------------------
  497|  25.5k|    uint32_t shift;
  498|  25.5k|    if (d.decimal_point == 0) {
  ------------------
  |  Branch (498:9): [True: 14.5k, False: 11.0k]
  ------------------
  499|  14.5k|      if (d.digits[0] >= 5) {
  ------------------
  |  Branch (499:11): [True: 6.84k, False: 7.73k]
  ------------------
  500|  6.84k|        break;
  501|  6.84k|      }
  502|  7.73k|      shift = (d.digits[0] < 2) ? 2 : 1;
  ------------------
  |  Branch (502:15): [True: 1.43k, False: 6.30k]
  ------------------
  503|  11.0k|    } else {
  504|  11.0k|      uint32_t n = uint32_t(-d.decimal_point);
  505|  11.0k|      shift = (n < num_powers) ? powers[n] : max_shift;
  ------------------
  |  Branch (505:15): [True: 2.40k, False: 8.59k]
  ------------------
  506|  11.0k|    }
  507|  18.7k|    decimal_left_shift(d, shift);
  508|  18.7k|    if (d.decimal_point > decimal_point_range) {
  ------------------
  |  Branch (508:9): [True: 0, False: 18.7k]
  ------------------
  509|       |      // we want to get infinity:
  510|      0|      answer.power2 = 0xFF;
  511|      0|      answer.mantissa = 0;
  512|      0|      return answer;
  513|      0|    }
  514|  18.7k|    exp2 -= int32_t(shift);
  515|  18.7k|  }
  516|       |  // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2].
  517|  6.84k|  exp2--;
  518|  6.84k|  constexpr int32_t minimum_exponent = binary::minimum_exponent();
  519|  7.33k|  while ((minimum_exponent + 1) > exp2) {
  ------------------
  |  Branch (519:10): [True: 488, False: 6.84k]
  ------------------
  520|    488|    uint32_t n = uint32_t((minimum_exponent + 1) - exp2);
  521|    488|    if (n > max_shift) {
  ------------------
  |  Branch (521:9): [True: 0, False: 488]
  ------------------
  522|      0|      n = max_shift;
  523|      0|    }
  524|    488|    decimal_right_shift(d, n);
  525|    488|    exp2 += int32_t(n);
  526|    488|  }
  527|  6.84k|  if ((exp2 - minimum_exponent) >= binary::infinite_power()) {
  ------------------
  |  Branch (527:7): [True: 181, False: 6.66k]
  ------------------
  528|    181|    answer.power2 = binary::infinite_power();
  529|    181|    answer.mantissa = 0;
  530|    181|    return answer;
  531|    181|  }
  532|       |
  533|  6.66k|  const int mantissa_size_in_bits = binary::mantissa_explicit_bits() + 1;
  534|  6.66k|  decimal_left_shift(d, mantissa_size_in_bits);
  535|       |
  536|  6.66k|  uint64_t mantissa = round(d);
  537|       |  // It is possible that we have an overflow, in which case we need
  538|       |  // to shift back.
  539|  6.66k|  if (mantissa >= (uint64_t(1) << mantissa_size_in_bits)) {
  ------------------
  |  Branch (539:7): [True: 1.57k, False: 5.09k]
  ------------------
  540|  1.57k|    decimal_right_shift(d, 1);
  541|  1.57k|    exp2 += 1;
  542|  1.57k|    mantissa = round(d);
  543|  1.57k|    if ((exp2 - minimum_exponent) >= binary::infinite_power()) {
  ------------------
  |  Branch (543:9): [True: 6, False: 1.56k]
  ------------------
  544|      6|      answer.power2 = binary::infinite_power();
  545|      6|      answer.mantissa = 0;
  546|      6|      return answer;
  547|      6|    }
  548|  1.57k|  }
  549|  6.66k|  answer.power2 = exp2 - binary::minimum_exponent();
  550|  6.66k|  if (mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) {
  ------------------
  |  Branch (550:7): [True: 488, False: 6.17k]
  ------------------
  551|    488|    answer.power2--;
  552|    488|  }
  553|  6.66k|  answer.mantissa =
  554|  6.66k|      mantissa & ((uint64_t(1) << binary::mantissa_explicit_bits()) - 1);
  555|  6.66k|  return answer;
  556|  6.66k|}
_ZN8simdjson8internal17adjusted_mantissaC2Ev:
   36|  7.30k|  adjusted_mantissa() : mantissa(0), power2(0) {}
_ZN8simdjson8internal13binary_formatIdE14infinite_powerEv:
   61|  8.76k|template <> constexpr int binary_format<double>::infinite_power() {
   62|  8.76k|  return 0x7FF;
   63|  8.76k|}
_ZN8simdjson8internal13binary_formatIdE16minimum_exponentEv:
   58|  6.66k|template <> constexpr int binary_format<double>::minimum_exponent() {
   59|  6.66k|  return -1023;
   60|  6.66k|}

simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_120json_character_block6scalarEv:
   17|  3.08M|  simdjson_inline uint64_t scalar() const noexcept { return ~(op() | whitespace()); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_120json_character_block2opEv:
   16|  4.62M|  simdjson_inline uint64_t op() const noexcept { return _op; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_120json_character_block10whitespaceEv:
   15|  3.08M|  simdjson_inline uint64_t whitespace() const noexcept { return _whitespace; }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EEC2EPKhm:
   83|  10.8k|simdjson_inline buf_block_reader<STEP_SIZE>::buf_block_reader(const uint8_t *_buf, size_t _len) : buf{_buf}, len{_len}, lenminusstep{len < STEP_SIZE ? 0 : len - STEP_SIZE}, idx{0} {}
  ------------------
  |  Branch (83:134): [True: 8.88k, False: 1.97k]
  ------------------
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EE14has_full_blockEv:
   89|   770k|simdjson_inline bool buf_block_reader<STEP_SIZE>::has_full_block() const {
   90|   770k|  return idx < lenminusstep;
   91|   770k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EE7advanceEv:
  107|   770k|simdjson_inline void buf_block_reader<STEP_SIZE>::advance() {
  108|   770k|  idx += STEP_SIZE;
  109|   770k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EE10full_blockEv:
   94|   759k|simdjson_inline const uint8_t *buf_block_reader<STEP_SIZE>::full_block() const {
   95|   759k|  return &buf[idx];
   96|   759k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EE13get_remainderEPh:
   99|  10.8k|simdjson_inline size_t buf_block_reader<STEP_SIZE>::get_remainder(uint8_t *dst) const {
  100|  10.8k|  if(len == idx) { return 0; } // memcpy(dst, null, 0) will trigger an error with some sanitizers
  ------------------
  |  Branch (100:6): [True: 0, False: 10.8k]
  ------------------
  101|  10.8k|  std::memset(dst, 0x20, STEP_SIZE); // std::memset STEP_SIZE because it's more efficient to write out 8 or 16 bytes at once.
  102|  10.8k|  std::memcpy(dst, buf + idx, len - idx);
  103|  10.8k|  return len - idx;
  104|  10.8k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage116buf_block_readerILm128EE11block_indexEv:
   86|  1.55M|simdjson_inline size_t buf_block_reader<STEP_SIZE>::block_index() { return idx; }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage119json_escape_scanner4nextEm:
   50|  1.54M|  simdjson_really_inline escaped_and_escape next(uint64_t backslash) noexcept {
   51|       |
   52|  1.54M|#if !SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
   53|  1.54M|    if (!backslash) { return {next_escaped_without_backslashes(), 0}; }
  ------------------
  |  Branch (53:9): [True: 1.52M, False: 12.4k]
  ------------------
   54|  12.4k|#endif
   55|       |
   56|       |    // |                                | Mask (shows characters instead of 1's) | Depth | Instructions        |
   57|       |    // |--------------------------------|----------------------------------------|-------|---------------------|
   58|       |    // | string                         | `\\n_\\\n___\\\n___\\\\___\\\\__\\\`   |       |                     |
   59|       |    // |                                | `    even   odd    even   odd   odd`   |       |                     |
   60|       |    // | potential_escape               | ` \  \\\    \\\    \\\\   \\\\  \\\`   | 1     | 1 (backslash & ~first_is_escaped)
   61|       |    // | escape_and_terminal_code       | ` \n \ \n   \ \n   \ \    \ \   \ \`   | 5     | 5 (next_escape_and_terminal_code())
   62|       |    // | escaped                        | `\    \ n    \ n    \ \    \ \   \ ` X | 6     | 7 (escape_and_terminal_code ^ (potential_escape | first_is_escaped))
   63|       |    // | escape                         | `    \ \    \ \    \ \    \ \   \ \`   | 6     | 8 (escape_and_terminal_code & backslash)
   64|       |    // | first_is_escaped               | `\                                 `   | 7 (*) | 9 (escape >> 63) ()
   65|       |    //                                                                               (*) this is not needed until the next iteration
   66|  12.4k|    uint64_t escape_and_terminal_code = next_escape_and_terminal_code(backslash & ~this->next_is_escaped);
   67|  12.4k|    uint64_t escaped = escape_and_terminal_code ^ (backslash | this->next_is_escaped);
   68|  12.4k|    uint64_t escape = escape_and_terminal_code & backslash;
   69|  12.4k|    this->next_is_escaped = escape >> 63;
   70|  12.4k|    return {escaped, escape};
   71|  1.54M|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage119json_escape_scanner32next_escaped_without_backslashesEv:
   76|  1.52M|  simdjson_really_inline uint64_t next_escaped_without_backslashes() noexcept {
   77|  1.52M|    uint64_t escaped = this->next_is_escaped;
   78|  1.52M|    this->next_is_escaped = 0;
   79|  1.52M|    return escaped;
   80|  1.52M|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage119json_escape_scanner29next_escape_and_terminal_codeEm:
   96|  12.4k|  static simdjson_really_inline uint64_t next_escape_and_terminal_code(uint64_t potential_escape) noexcept {
   97|       |    // If we were to just shift and mask out any odd bits, we'd actually get a *half* right answer:
   98|       |    // any even-aligned backslash runs would be correct! Odd-aligned backslash runs would be
   99|       |    // inverted (\\\ would be 010 instead of 101).
  100|       |    //
  101|       |    // ```
  102|       |    // string:              | ____\\\\_\\\\_____ |
  103|       |    // maybe_escaped | ODD  |     \ \   \ \      |
  104|       |    //               even-aligned ^^^  ^^^^ odd-aligned
  105|       |    // ```
  106|       |    //
  107|       |    // Taking that into account, our basic strategy is:
  108|       |    //
  109|       |    // 1. Use subtraction to produce a mask with 1's for even-aligned runs and 0's for
  110|       |    //    odd-aligned runs.
  111|       |    // 2. XOR all odd bits, which masks out the odd bits in even-aligned runs, and brings IN the
  112|       |    //    odd bits in odd-aligned runs.
  113|       |    // 3. & with backslash to clean up any stray bits.
  114|       |    // runs are set to 0, and then XORing with "odd":
  115|       |    //
  116|       |    // |                                | Mask (shows characters instead of 1's) | Instructions        |
  117|       |    // |--------------------------------|----------------------------------------|---------------------|
  118|       |    // | string                         | `\\n_\\\n___\\\n___\\\\___\\\\__\\\`   |
  119|       |    // |                                | `    even   odd    even   odd   odd`   |
  120|       |    // | maybe_escaped                  | `  n  \\n    \\n    \\\_   \\\_  \\` X | 1 (potential_escape << 1)
  121|       |    // | maybe_escaped_and_odd          | ` \n_ \\n _ \\\n_ _ \\\__ _\\\_ \\\`   | 1 (maybe_escaped | odd)
  122|       |    // | even_series_codes_and_odd      | `  n_\\\  _    n_ _\\\\ _     _    `   | 1 (maybe_escaped_and_odd - potential_escape)
  123|       |    // | escape_and_terminal_code       | ` \n \ \n   \ \n   \ \    \ \   \ \`   | 1 (^ odd)
  124|       |    //
  125|       |
  126|       |    // Escaped characters are characters following an escape.
  127|  12.4k|    uint64_t maybe_escaped = potential_escape << 1;
  128|       |
  129|       |    // To distinguish odd from even escape sequences, therefore, we turn on any *starting*
  130|       |    // escapes that are on an odd byte. (We actually bring in all odd bits, for speed.)
  131|       |    // - Odd runs of backslashes are 0000, and the code at the end ("n" in \n or \\n) is 1.
  132|       |    // - Odd runs of backslashes are 1111, and the code at the end ("n" in \n or \\n) is 0.
  133|       |    // - All other odd bytes are 1, and even bytes are 0.
  134|  12.4k|    uint64_t maybe_escaped_and_odd_bits     = maybe_escaped | ODD_BITS;
  135|  12.4k|    uint64_t even_series_codes_and_odd_bits = maybe_escaped_and_odd_bits - potential_escape;
  136|       |
  137|       |    // Now we flip all odd bytes back with xor. This:
  138|       |    // - Makes odd runs of backslashes go from 0000 to 1010
  139|       |    // - Makes even runs of backslashes go from 1111 to 1010
  140|       |    // - Sets actually-escaped codes to 1 (the n in \n and \\n: \n = 11, \\n = 100)
  141|       |    // - Resets all other bytes to 0
  142|  12.4k|    return even_series_codes_and_odd_bits ^ ODD_BITS;
  143|  12.4k|  }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage112json_scannerC2Ev:
  108|  10.8k|  json_scanner() = default;
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage112json_scanner4nextERKNS1_4simd8simd8x64IhEE:
  134|  1.54M|simdjson_inline json_block json_scanner::next(const simd::simd8x64<uint8_t>& in) {
  135|  1.54M|  json_string_block strings = string_scanner.next(in);
  136|       |  // identifies the white-space and the structural characters
  137|  1.54M|  json_character_block characters = json_character_block::classify(in);
  138|       |  // The term "scalar" refers to anything except structural characters and white space
  139|       |  // (so letters, numbers, quotes).
  140|       |  // We want follows_scalar to mark anything that follows a non-quote scalar (so letters and numbers).
  141|       |  //
  142|       |  // A terminal quote should either be followed by a structural character (comma, brace, bracket, colon)
  143|       |  // or nothing. However, we still want ' "a string"true ' to mark the 't' of 'true' as a potential
  144|       |  // pseudo-structural character just like we would if we had  ' "a string" true '; otherwise we
  145|       |  // may need to add an extra check when parsing strings.
  146|       |  //
  147|       |  // Performance: there are many ways to skin this cat.
  148|  1.54M|  const uint64_t nonquote_scalar = characters.scalar() & ~strings.quote();
  149|  1.54M|  uint64_t follows_nonquote_scalar = follows(nonquote_scalar, prev_scalar);
  150|       |  // We are returning a function-local object so either we get a move constructor
  151|       |  // or we get copy elision.
  152|  1.54M|  return json_block(
  153|  1.54M|    strings,// strings is a function-local object so either it moves or the copy is elided.
  154|  1.54M|    characters,
  155|  1.54M|    follows_nonquote_scalar
  156|  1.54M|  );
  157|  1.54M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage17followsEmRm:
  128|  1.54M|simdjson_inline uint64_t follows(const uint64_t match, uint64_t &overflow) {
  129|  1.54M|  const uint64_t result = match << 1 | overflow;
  130|  1.54M|  overflow = match >> 63;
  131|  1.54M|  return result;
  132|  1.54M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage110json_blockC2ENS2_17json_string_blockENS1_20json_character_blockEm:
   38|  1.54M|  _string(string), _characters(characters), _follows_potential_nonquote_scalar(follows_potential_nonquote_scalar) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage112json_scanner6finishEv:
  159|  10.8k|simdjson_inline error_code json_scanner::finish() {
  160|  10.8k|  return string_scanner.finish();
  161|  10.8k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage110json_block16structural_startEv:
   44|  1.54M|  simdjson_inline uint64_t structural_start() const noexcept { return potential_structural_start() & ~_string.string_tail(); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage110json_block26potential_structural_startEv:
   68|  1.54M|  simdjson_inline uint64_t potential_structural_start() const noexcept { return _characters.op() | potential_scalar_start(); }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage110json_block22potential_scalar_startEv:
   73|  1.54M|  simdjson_inline uint64_t potential_scalar_start() const noexcept {
   74|       |    // The term "scalar" refers to anything except structural characters and white space
   75|       |    // (so letters, numbers, quotes).
   76|       |    // Whenever it is preceded by something that is not a structural element ({,},[,],:, ") nor a white-space
   77|       |    // then we know that it is irrelevant structurally.
   78|  1.54M|    return _characters.scalar() & ~follows_potential_scalar();
   79|  1.54M|  }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage110json_block24follows_potential_scalarEv:
   84|  1.54M|  simdjson_inline uint64_t follows_potential_scalar() const noexcept {
   85|       |    // _follows_potential_nonquote_scalar: is defined as marking any character that follows a character
   86|       |    // that is not a structural element ({,},[,],:, comma) nor a quote (") and that is not a
   87|       |    // white space.
   88|       |    // It is understood that within quoted region, anything at all could be marked (irrelevant).
   89|  1.54M|    return _follows_potential_nonquote_scalar;
   90|  1.54M|  }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage110json_block23non_quote_inside_stringEm:
   51|  1.54M|  simdjson_inline uint64_t non_quote_inside_string(uint64_t mask) const noexcept { return _string.non_quote_inside_string(mask); }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage119json_string_scanner4nextERKNS1_4simd8simd8x64IhEE:
   62|  1.54M|simdjson_really_inline json_string_block json_string_scanner::next(const simd::simd8x64<uint8_t>& in) {
   63|  1.54M|  const uint64_t backslash = in.eq('\\');
   64|  1.54M|  const uint64_t escaped = escape_scanner.next(backslash).escaped;
   65|  1.54M|  const uint64_t quote = in.eq('"') & ~escaped;
   66|       |
   67|       |  //
   68|       |  // prefix_xor flips on bits inside the string (and flips off the end quote).
   69|       |  //
   70|       |  // Then we xor with prev_in_string: if we were in a string already, its effect is flipped
   71|       |  // (characters inside strings are outside, and characters outside strings are inside).
   72|       |  //
   73|  1.54M|  const uint64_t in_string = prefix_xor(quote) ^ prev_in_string;
   74|       |
   75|       |  //
   76|       |  // Check if we're still in a string at the end of the box so the next block will know
   77|       |  //
   78|  1.54M|  prev_in_string = uint64_t(static_cast<int64_t>(in_string) >> 63);
   79|       |
   80|       |  // Use ^ to turn the beginning quote off, and the end quote on.
   81|       |
   82|       |  // We are returning a function-local object so either we get a move constructor
   83|       |  // or we get copy elision.
   84|  1.54M|  return json_string_block(escaped, quote, in_string);
   85|  1.54M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage117json_string_blockC2Emmm:
   17|  1.54M|  _escaped(escaped), _quote(quote), _in_string(in_string) {}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage117json_string_block5quoteEv:
   22|  1.54M|  simdjson_really_inline uint64_t quote() const { return _quote; }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage119json_string_scanner6finishEv:
   87|  10.8k|simdjson_really_inline error_code json_string_scanner::finish() {
   88|  10.8k|  if (prev_in_string) {
  ------------------
  |  Branch (88:7): [True: 174, False: 10.6k]
  ------------------
   89|    174|    return UNCLOSED_STRING;
   90|    174|  }
   91|  10.6k|  return SUCCESS;
   92|  10.8k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage117json_string_block11string_tailEv:
   30|  1.54M|  simdjson_really_inline uint64_t string_tail() const { return _in_string ^ _quote; }
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage117json_string_block23non_quote_inside_stringEm:
   26|  1.54M|  simdjson_really_inline uint64_t non_quote_inside_string(uint64_t mask) const { return mask & _in_string; }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage123json_structural_indexer5indexILm128EEENS_10error_codeEPKhmRNS0_25dom_parser_implementationENS_11stage1_modeE:
  194|  10.8k|error_code json_structural_indexer::index(const uint8_t *buf, size_t len, dom_parser_implementation &parser, stage1_mode partial) noexcept {
  195|  10.8k|  if (simdjson_unlikely(len > parser.capacity())) { return CAPACITY; }
  ------------------
  |  |  106|  10.8k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 0, False: 10.8k]
  |  |  ------------------
  ------------------
  196|       |  // We guard the rest of the code so that we can assume that len > 0 throughout.
  197|  10.8k|  if (len == 0) { return EMPTY; }
  ------------------
  |  Branch (197:7): [True: 1, False: 10.8k]
  ------------------
  198|  10.8k|  if (is_streaming(partial)) {
  ------------------
  |  Branch (198:7): [True: 0, False: 10.8k]
  ------------------
  199|      0|    len = trim_partial_utf8(buf, len);
  200|       |    // If you end up with an empty window after trimming
  201|       |    // the partial UTF-8 bytes, then chances are good that you
  202|       |    // have an UTF-8 formatting error.
  203|      0|    if(len == 0) { return UTF8_ERROR; }
  ------------------
  |  Branch (203:8): [True: 0, False: 0]
  ------------------
  204|      0|  }
  205|  10.8k|  buf_block_reader<STEP_SIZE> reader(buf, len);
  206|  10.8k|  json_structural_indexer indexer(parser.structural_indexes.get());
  207|       |
  208|       |  // Read all but the last block
  209|   770k|  while (reader.has_full_block()) {
  ------------------
  |  Branch (209:10): [True: 759k, False: 10.8k]
  ------------------
  210|   759k|    indexer.step<STEP_SIZE>(reader.full_block(), reader);
  211|   759k|  }
  212|       |  // Take care of the last block (will always be there unless file is empty which is
  213|       |  // not supposed to happen.)
  214|  10.8k|  uint8_t block[STEP_SIZE];
  215|  10.8k|  if (simdjson_unlikely(reader.get_remainder(block) == 0)) { return UNEXPECTED_ERROR; }
  ------------------
  |  |  106|  10.8k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 0, False: 10.8k]
  |  |  ------------------
  ------------------
  216|  10.8k|  indexer.step<STEP_SIZE>(block, reader);
  217|  10.8k|  return indexer.finish(parser, reader.block_index(), len, partial);
  218|  10.8k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage123json_structural_indexerC2EPj:
  153|  10.8k|simdjson_inline json_structural_indexer::json_structural_indexer(uint32_t *structural_indexes) : indexer{structural_indexes} {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexerC2EPj:
   28|  10.8k|  simdjson_inline bit_indexer(uint32_t *index_buf) : tail(index_buf) {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage123json_structural_indexer4stepILm128EEEvPKhRNS2_16buf_block_readerIXT_EEE:
  221|   770k|simdjson_inline void json_structural_indexer::step<128>(const uint8_t *block, buf_block_reader<128> &reader) noexcept {
  222|   770k|  simd::simd8x64<uint8_t> in_1(block);
  223|   770k|  simd::simd8x64<uint8_t> in_2(block+64);
  224|   770k|  json_block block_1 = scanner.next(in_1);
  225|   770k|  json_block block_2 = scanner.next(in_2);
  226|   770k|  this->next(in_1, block_1, reader.block_index());
  227|   770k|  this->next(in_2, block_2, reader.block_index()+64);
  228|   770k|  reader.advance();
  229|   770k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage123json_structural_indexer4nextERKNS1_4simd8simd8x64IhEERKNS2_10json_blockEm:
  239|  1.54M|simdjson_inline void json_structural_indexer::next(const simd::simd8x64<uint8_t>& in, const json_block& block, size_t idx) {
  240|  1.54M|  uint64_t unescaped = in.lteq(0x1F);
  241|  1.54M|#if SIMDJSON_UTF8VALIDATION
  242|  1.54M|  checker.check_next_input(in);
  243|  1.54M|#endif
  244|  1.54M|  indexer.write(uint32_t(idx-64), prev_structurals); // Output *last* iteration's structurals to the parser
  245|  1.54M|  prev_structurals = block.structural_start();
  246|  1.54M|  unescaped_chars_error |= block.non_quote_inside_string(unescaped);
  247|  1.54M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer5writeEjm:
   93|  1.55M|  simdjson_inline void write(uint32_t idx, uint64_t bits) {
   94|       |    // In some instances, the next branch is expensive because it is mispredicted.
   95|       |    // Unfortunately, in other cases,
   96|       |    // it helps tremendously.
   97|  1.55M|    if (bits == 0)
  ------------------
  |  Branch (97:9): [True: 1.14M, False: 407k]
  ------------------
   98|  1.14M|        return;
   99|       |
  100|   407k|    int cnt = static_cast<int>(count_ones(bits));
  101|       |
  102|       |#if SIMDJSON_PREFER_REVERSE_BITS
  103|       |    bits = reverse_bits(bits);
  104|       |#endif
  105|       |#ifdef SIMDJSON_STRUCTURAL_INDEXER_STEP
  106|       |    static constexpr const int STEP = SIMDJSON_STRUCTURAL_INDEXER_STEP;
  107|       |#else
  108|   407k|    static constexpr const int STEP = 4;
  109|   407k|#endif
  110|   407k|    static constexpr const int STEP_UNTIL = 24;
  111|       |
  112|   407k|    write_indexes_stepped<0, STEP_UNTIL, STEP>(idx, bits, cnt);
  113|   407k|    SIMDJSON_IF_CONSTEXPR (STEP_UNTIL < 64) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
  114|   407k|      if (simdjson_unlikely(STEP_UNTIL < cnt)) {
  ------------------
  |  |  106|   407k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 365k, False: 41.7k]
  |  |  ------------------
  ------------------
  115|  4.78M|        for (int i=STEP_UNTIL; i<cnt; i++) {
  ------------------
  |  Branch (115:32): [True: 4.41M, False: 365k]
  ------------------
  116|  4.41M|          write_index(idx, bits, i);
  117|  4.41M|        }
  118|   365k|      }
  119|   407k|    }
  120|       |
  121|   407k|    this->tail += cnt;
  122|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi0ELi24ELi4EEEijRmi:
   72|   407k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   407k|    write_indexes<START, STEP>(idx, bits);
   74|   407k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|   407k|      if (simdjson_unlikely((START+STEP) < cnt)) {
  ------------------
  |  |  106|   407k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 391k, False: 15.7k]
  |  |  ------------------
  ------------------
   76|   391k|        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|   391k|      }
   78|   407k|    }
   79|   407k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi0ELi4EEEijRm:
   63|   407k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   407k|    write_index(idx, bits, START);
   65|   407k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   407k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   407k|    }
   68|   407k|    return START+N;
   69|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi1ELi3EEEijRm:
   63|   407k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   407k|    write_index(idx, bits, START);
   65|   407k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   407k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   407k|    }
   68|   407k|    return START+N;
   69|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi2ELi2EEEijRm:
   63|   407k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   407k|    write_index(idx, bits, START);
   65|   407k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   407k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   407k|    }
   68|   407k|    return START+N;
   69|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi3ELi1EEEijRm:
   63|   407k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   407k|    write_index(idx, bits, START);
   65|   407k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   407k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   407k|    return START+N;
   69|   407k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi4ELi24ELi4EEEijRmi:
   72|   391k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   391k|    write_indexes<START, STEP>(idx, bits);
   74|   391k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   391k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|   391k|      if (simdjson_unlikely((START+STEP) < cnt)) {
  ------------------
  |  |  106|   391k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 383k, False: 8.24k]
  |  |  ------------------
  ------------------
   76|   383k|        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|   383k|      }
   78|   391k|    }
   79|   391k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   391k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi4ELi4EEEijRm:
   63|   391k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   391k|    write_index(idx, bits, START);
   65|   391k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   391k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   391k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   391k|    }
   68|   391k|    return START+N;
   69|   391k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi5ELi3EEEijRm:
   63|   391k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   391k|    write_index(idx, bits, START);
   65|   391k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   391k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   391k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   391k|    }
   68|   391k|    return START+N;
   69|   391k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi6ELi2EEEijRm:
   63|   391k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   391k|    write_index(idx, bits, START);
   65|   391k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   391k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   391k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   391k|    }
   68|   391k|    return START+N;
   69|   391k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi7ELi1EEEijRm:
   63|   391k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   391k|    write_index(idx, bits, START);
   65|   391k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   391k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   391k|    return START+N;
   69|   391k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi8ELi24ELi4EEEijRmi:
   72|   383k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   383k|    write_indexes<START, STEP>(idx, bits);
   74|   383k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   383k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|   383k|      if (simdjson_unlikely((START+STEP) < cnt)) {
  ------------------
  |  |  106|   383k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 378k, False: 4.38k]
  |  |  ------------------
  ------------------
   76|   378k|        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|   378k|      }
   78|   383k|    }
   79|   383k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   383k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi8ELi4EEEijRm:
   63|   383k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   383k|    write_index(idx, bits, START);
   65|   383k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   383k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   383k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   383k|    }
   68|   383k|    return START+N;
   69|   383k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi9ELi3EEEijRm:
   63|   383k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   383k|    write_index(idx, bits, START);
   65|   383k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   383k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   383k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   383k|    }
   68|   383k|    return START+N;
   69|   383k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi10ELi2EEEijRm:
   63|   383k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   383k|    write_index(idx, bits, START);
   65|   383k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   383k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   383k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   383k|    }
   68|   383k|    return START+N;
   69|   383k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi11ELi1EEEijRm:
   63|   383k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   383k|    write_index(idx, bits, START);
   65|   383k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   383k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   383k|    return START+N;
   69|   383k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi12ELi24ELi4EEEijRmi:
   72|   378k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   378k|    write_indexes<START, STEP>(idx, bits);
   74|   378k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   378k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|   378k|      if (simdjson_unlikely((START+STEP) < cnt)) {
  ------------------
  |  |  106|   378k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 372k, False: 6.12k]
  |  |  ------------------
  ------------------
   76|   372k|        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|   372k|      }
   78|   378k|    }
   79|   378k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   378k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi12ELi4EEEijRm:
   63|   378k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   378k|    write_index(idx, bits, START);
   65|   378k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   378k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   378k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   378k|    }
   68|   378k|    return START+N;
   69|   378k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi13ELi3EEEijRm:
   63|   378k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   378k|    write_index(idx, bits, START);
   65|   378k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   378k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   378k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   378k|    }
   68|   378k|    return START+N;
   69|   378k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi14ELi2EEEijRm:
   63|   378k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   378k|    write_index(idx, bits, START);
   65|   378k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   378k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   378k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   378k|    }
   68|   378k|    return START+N;
   69|   378k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi15ELi1EEEijRm:
   63|   378k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   378k|    write_index(idx, bits, START);
   65|   378k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   378k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   378k|    return START+N;
   69|   378k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi16ELi24ELi4EEEijRmi:
   72|   372k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   372k|    write_indexes<START, STEP>(idx, bits);
   74|   372k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   372k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|   372k|      if (simdjson_unlikely((START+STEP) < cnt)) {
  ------------------
  |  |  106|   372k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 369k, False: 3.33k]
  |  |  ------------------
  ------------------
   76|   369k|        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|   369k|      }
   78|   372k|    }
   79|   372k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   372k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi16ELi4EEEijRm:
   63|   372k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   372k|    write_index(idx, bits, START);
   65|   372k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   372k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   372k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   372k|    }
   68|   372k|    return START+N;
   69|   372k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi17ELi3EEEijRm:
   63|   372k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   372k|    write_index(idx, bits, START);
   65|   372k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   372k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   372k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   372k|    }
   68|   372k|    return START+N;
   69|   372k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi18ELi2EEEijRm:
   63|   372k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   372k|    write_index(idx, bits, START);
   65|   372k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   372k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   372k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   372k|    }
   68|   372k|    return START+N;
   69|   372k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi19ELi1EEEijRm:
   63|   372k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   372k|    write_index(idx, bits, START);
   65|   372k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   372k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   372k|    return START+N;
   69|   372k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer21write_indexes_steppedILi20ELi24ELi4EEEijRmi:
   72|   369k|  simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
   73|   369k|    write_indexes<START, STEP>(idx, bits);
   74|   369k|    SIMDJSON_IF_CONSTEXPR ((START+STEP)  < END) {
  ------------------
  |  |   47|   369k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   75|       |      if (simdjson_unlikely((START+STEP) < cnt)) {
   76|       |        write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
   77|       |      }
   78|       |    }
   79|   369k|    return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
  ------------------
  |  Branch (79:12): [Folded - Ignored]
  ------------------
   80|   369k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi20ELi4EEEijRm:
   63|   369k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   369k|    write_index(idx, bits, START);
   65|   369k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   369k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   369k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   369k|    }
   68|   369k|    return START+N;
   69|   369k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi21ELi3EEEijRm:
   63|   369k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   369k|    write_index(idx, bits, START);
   65|   369k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   369k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   369k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   369k|    }
   68|   369k|    return START+N;
   69|   369k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi22ELi2EEEijRm:
   63|   369k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   369k|    write_index(idx, bits, START);
   65|   369k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   369k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|   369k|      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|   369k|    }
   68|   369k|    return START+N;
   69|   369k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer13write_indexesILi23ELi1EEEijRm:
   63|   369k|  simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
   64|   369k|    write_index(idx, bits, START);
   65|   369k|    SIMDJSON_IF_CONSTEXPR (N > 1) {
  ------------------
  |  |   47|   369k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
   66|       |      write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
   67|       |    }
   68|   369k|    return START+N;
   69|   369k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage111bit_indexer11write_indexEjRmi:
   56|  13.6M|  simdjson_inline void write_index(uint32_t idx, uint64_t& bits, int i) {
   57|  13.6M|    this->tail[i] = idx + trailing_zeroes(bits);
   58|  13.6M|    bits = clear_lowest_bit(bits);
   59|  13.6M|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage123json_structural_indexer6finishERNS0_25dom_parser_implementationEmmNS_11stage1_modeE:
  249|  10.8k|simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementation &parser, size_t idx, size_t len, stage1_mode partial) {
  250|       |  // Write out the final iteration's structurals
  251|  10.8k|  indexer.write(uint32_t(idx-64), prev_structurals);
  252|  10.8k|  error_code error = scanner.finish();
  253|       |  // We deliberately break down the next expression so that it is
  254|       |  // human readable.
  255|  10.8k|  const bool should_we_exit = is_streaming(partial) ?
  ------------------
  |  Branch (255:31): [True: 0, False: 10.8k]
  ------------------
  256|      0|    ((error != SUCCESS) && (error != UNCLOSED_STRING)) // when partial we tolerate UNCLOSED_STRING
  ------------------
  |  Branch (256:6): [True: 0, False: 0]
  |  Branch (256:28): [True: 0, False: 0]
  ------------------
  257|  10.8k|    : (error != SUCCESS); // if partial is false, we must have SUCCESS
  258|  10.8k|  const bool have_unclosed_string = (error == UNCLOSED_STRING);
  259|  10.8k|  if (simdjson_unlikely(should_we_exit)) { return error; }
  ------------------
  |  |  106|  10.8k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 174, False: 10.6k]
  |  |  ------------------
  ------------------
  260|       |
  261|  10.6k|  if (unescaped_chars_error) {
  ------------------
  |  Branch (261:7): [True: 178, False: 10.5k]
  ------------------
  262|    178|    return UNESCAPED_CHARS;
  263|    178|  }
  264|  10.5k|  parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get());
  265|       |  /***
  266|       |   * The On-Demand API requires special padding.
  267|       |   *
  268|       |   * This is related to https://github.com/simdjson/simdjson/issues/906
  269|       |   * Basically, we want to make sure that if the parsing continues beyond the last (valid)
  270|       |   * structural character, it quickly stops.
  271|       |   * Only three structural characters can be repeated without triggering an error in JSON:  [,] and }.
  272|       |   * We repeat the padding character (at 'len'). We don't know what it is, but if the parsing
  273|       |   * continues, then it must be [,] or }.
  274|       |   * Suppose it is ] or }. We backtrack to the first character, what could it be that would
  275|       |   * not trigger an error? It could be ] or } but no, because you can't start a document that way.
  276|       |   * It can't be a comma, a colon or any simple value. So the only way we could continue is
  277|       |   * if the repeated character is [. But if so, the document must start with [. But if the document
  278|       |   * starts with [, it should end with ]. If we enforce that rule, then we would get
  279|       |   * ][[ which is invalid.
  280|       |   *
  281|       |   * This is illustrated with the test array_iterate_unclosed_error() on the following input:
  282|       |   * R"({ "a": [,,)"
  283|       |   **/
  284|  10.5k|  parser.structural_indexes[parser.n_structural_indexes] = uint32_t(len); // used later in partial == stage1_mode::streaming_final
  285|  10.5k|  parser.structural_indexes[parser.n_structural_indexes + 1] = uint32_t(len);
  286|  10.5k|  parser.structural_indexes[parser.n_structural_indexes + 2] = 0;
  287|  10.5k|  parser.next_structural_index = 0;
  288|       |  // a valid JSON file cannot have zero structural indexes - we should have found something
  289|  10.5k|  if (simdjson_unlikely(parser.n_structural_indexes == 0u)) {
  ------------------
  |  |  106|  10.5k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 1, False: 10.5k]
  |  |  ------------------
  ------------------
  290|      1|    return EMPTY;
  291|      1|  }
  292|  10.5k|  if (simdjson_unlikely(parser.structural_indexes[parser.n_structural_indexes - 1] > len)) {
  ------------------
  |  |  106|  10.5k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 0, False: 10.5k]
  |  |  ------------------
  ------------------
  293|      0|    return UNEXPECTED_ERROR;
  294|      0|  }
  295|  10.5k|  if (partial == stage1_mode::streaming_partial) {
  ------------------
  |  Branch (295:7): [True: 0, False: 10.5k]
  ------------------
  296|       |    // If we have an unclosed string, then the last structural
  297|       |    // will be the quote and we want to make sure to omit it.
  298|      0|    if(have_unclosed_string) {
  ------------------
  |  Branch (298:8): [True: 0, False: 0]
  ------------------
  299|      0|      parser.n_structural_indexes--;
  300|       |      // a valid JSON file cannot have zero structural indexes - we should have found something
  301|      0|      if (simdjson_unlikely(parser.n_structural_indexes == 0u)) { return CAPACITY; }
  ------------------
  |  |  106|      0|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  302|      0|    }
  303|       |    // We truncate the input to the end of the last complete document (or zero).
  304|      0|    auto new_structural_indexes = find_next_document_index(parser);
  305|      0|    if (new_structural_indexes == 0 && parser.n_structural_indexes > 0) {
  ------------------
  |  Branch (305:9): [True: 0, False: 0]
  |  Branch (305:40): [True: 0, False: 0]
  ------------------
  306|      0|      if(parser.structural_indexes[0] == 0) {
  ------------------
  |  Branch (306:10): [True: 0, False: 0]
  ------------------
  307|       |        // If the buffer is partial and we started at index 0 but the document is
  308|       |        // incomplete, it's too big to parse.
  309|      0|        return CAPACITY;
  310|      0|      } else {
  311|       |        // It is possible that the document could be parsed, we just had a lot
  312|       |        // of white space.
  313|      0|        parser.n_structural_indexes = 0;
  314|      0|        return EMPTY;
  315|      0|      }
  316|      0|    }
  317|       |
  318|      0|    parser.n_structural_indexes = new_structural_indexes;
  319|  10.5k|  } else if (partial == stage1_mode::streaming_final) {
  ------------------
  |  Branch (319:14): [True: 0, False: 10.5k]
  ------------------
  320|      0|    if(have_unclosed_string) { parser.n_structural_indexes--; }
  ------------------
  |  Branch (320:8): [True: 0, False: 0]
  ------------------
  321|       |    // We truncate the input to the end of the last complete document (or zero).
  322|       |    // Because partial == stage1_mode::streaming_final, it means that we may
  323|       |    // silently ignore trailing garbage. Though it sounds bad, we do it
  324|       |    // deliberately because many people who have streams of JSON documents
  325|       |    // will truncate them for processing. E.g., imagine that you are uncompressing
  326|       |    // the data from a size file or receiving it in chunks from the network. You
  327|       |    // may not know where exactly the last document will be. Meanwhile the
  328|       |    // document_stream instances allow people to know the JSON documents they are
  329|       |    // parsing (see the iterator.source() method).
  330|      0|    parser.n_structural_indexes = find_next_document_index(parser);
  331|       |    // We store the initial n_structural_indexes so that the client can see
  332|       |    // whether we used truncation. If initial_n_structural_indexes == parser.n_structural_indexes,
  333|       |    // then this will query parser.structural_indexes[parser.n_structural_indexes] which is len,
  334|       |    // otherwise, it will copy some prior index.
  335|      0|    parser.structural_indexes[parser.n_structural_indexes + 1] = parser.structural_indexes[parser.n_structural_indexes];
  336|       |    // This next line is critical, do not change it unless you understand what you are
  337|       |    // doing.
  338|      0|    parser.structural_indexes[parser.n_structural_indexes] = uint32_t(len);
  339|      0|    if (simdjson_unlikely(parser.n_structural_indexes == 0u)) {
  ------------------
  |  |  106|      0|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  340|       |        // We tolerate an unclosed string at the very end of the stream. Indeed, users
  341|       |        // often load their data in bulk without being careful and they want us to ignore
  342|       |        // the trailing garbage.
  343|      0|        return EMPTY;
  344|      0|    }
  345|      0|  }
  346|  10.5k|  checker.check_eof();
  347|  10.5k|  return checker.errors();
  348|  10.5k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation12utf8_checker16check_next_inputERKNS1_4simd8simd8x64IhEE:
  173|  1.54M|    simdjson_inline void check_next_input(const simd8x64<uint8_t>& input) {
  174|  1.54M|      if(simdjson_likely(is_ascii(input))) {
  ------------------
  |  |  103|  1.54M|  #define simdjson_likely(x) __builtin_expect(!!(x), 1)
  |  |  ------------------
  |  |  |  Branch (103:30): [True: 1.53M, False: 6.06k]
  |  |  ------------------
  ------------------
  175|  1.53M|        this->error |= this->prev_incomplete;
  176|  1.53M|      } else {
  177|       |        // you might think that a for-loop would work, but under Visual Studio, it is not good enough.
  178|  6.06k|        static_assert((simd8x64<uint8_t>::NUM_CHUNKS == 1)
  179|  6.06k|                ||(simd8x64<uint8_t>::NUM_CHUNKS == 2)
  180|  6.06k|                || (simd8x64<uint8_t>::NUM_CHUNKS == 4),
  181|  6.06k|                "We support one, two or four chunks per 64-byte block.");
  182|  6.06k|        SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 1) {
  ------------------
  |  |   47|  6.06k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
  183|       |          this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
  184|  6.06k|        } else SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 2) {
  ------------------
  |  |   47|  6.06k|#define SIMDJSON_IF_CONSTEXPR if constexpr
  ------------------
  185|  6.06k|          this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
  186|  6.06k|          this->check_utf8_bytes(input.chunks[1], input.chunks[0]);
  187|       |        } else SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 4) {
  188|       |          this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
  189|       |          this->check_utf8_bytes(input.chunks[1], input.chunks[0]);
  190|       |          this->check_utf8_bytes(input.chunks[2], input.chunks[1]);
  191|       |          this->check_utf8_bytes(input.chunks[3], input.chunks[2]);
  192|       |        }
  193|  6.06k|        this->prev_incomplete = is_incomplete(input.chunks[simd8x64<uint8_t>::NUM_CHUNKS-1]);
  194|  6.06k|        this->prev_input_block = input.chunks[simd8x64<uint8_t>::NUM_CHUNKS-1];
  195|  6.06k|      }
  196|  1.54M|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation12utf8_checker16check_utf8_bytesENS1_4simd5simd8IhEES6_:
  156|  12.1k|    simdjson_inline void check_utf8_bytes(const simd8<uint8_t> input, const simd8<uint8_t> prev_input) {
  157|       |      // Flip prev1...prev3 so we can easily determine if they are 2+, 3+ or 4+ lead bytes
  158|       |      // (2, 3, 4-byte leads become large positive numbers instead of small negative numbers)
  159|  12.1k|      simd8<uint8_t> prev1 = input.prev<1>(prev_input);
  160|  12.1k|      simd8<uint8_t> sc = check_special_cases(input, prev1);
  161|  12.1k|      this->error |= check_multibyte_lengths(input, prev_input, sc);
  162|  12.1k|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation19check_special_casesENS1_4simd5simd8IhEES5_:
   16|  12.1k|  simdjson_inline simd8<uint8_t> check_special_cases(const simd8<uint8_t> input, const simd8<uint8_t> prev1) {
   17|       |// Bit 0 = Too Short (lead byte/ASCII followed by lead byte/ASCII)
   18|       |// Bit 1 = Too Long (ASCII followed by continuation)
   19|       |// Bit 2 = Overlong 3-byte
   20|       |// Bit 4 = Surrogate
   21|       |// Bit 5 = Overlong 2-byte
   22|       |// Bit 7 = Two Continuations
   23|  12.1k|    constexpr const uint8_t TOO_SHORT   = 1<<0; // 11______ 0_______
   24|       |                                                // 11______ 11______
   25|  12.1k|    constexpr const uint8_t TOO_LONG    = 1<<1; // 0_______ 10______
   26|  12.1k|    constexpr const uint8_t OVERLONG_3  = 1<<2; // 11100000 100_____
   27|  12.1k|    constexpr const uint8_t SURROGATE   = 1<<4; // 11101101 101_____
   28|  12.1k|    constexpr const uint8_t OVERLONG_2  = 1<<5; // 1100000_ 10______
   29|  12.1k|    constexpr const uint8_t TWO_CONTS   = 1<<7; // 10______ 10______
   30|  12.1k|    constexpr const uint8_t TOO_LARGE   = 1<<3; // 11110100 1001____
   31|       |                                                // 11110100 101_____
   32|       |                                                // 11110101 1001____
   33|       |                                                // 11110101 101_____
   34|       |                                                // 1111011_ 1001____
   35|       |                                                // 1111011_ 101_____
   36|       |                                                // 11111___ 1001____
   37|       |                                                // 11111___ 101_____
   38|  12.1k|    constexpr const uint8_t TOO_LARGE_1000 = 1<<6;
   39|       |                                                // 11110101 1000____
   40|       |                                                // 1111011_ 1000____
   41|       |                                                // 11111___ 1000____
   42|  12.1k|    constexpr const uint8_t OVERLONG_4  = 1<<6; // 11110000 1000____
   43|       |
   44|  12.1k|    const simd8<uint8_t> byte_1_high = prev1.shr<4>().lookup_16<uint8_t>(
   45|       |      // 0_______ ________ <ASCII in byte 1>
   46|  12.1k|      TOO_LONG, TOO_LONG, TOO_LONG, TOO_LONG,
   47|  12.1k|      TOO_LONG, TOO_LONG, TOO_LONG, TOO_LONG,
   48|       |      // 10______ ________ <continuation in byte 1>
   49|  12.1k|      TWO_CONTS, TWO_CONTS, TWO_CONTS, TWO_CONTS,
   50|       |      // 1100____ ________ <two byte lead in byte 1>
   51|  12.1k|      TOO_SHORT | OVERLONG_2,
   52|       |      // 1101____ ________ <two byte lead in byte 1>
   53|  12.1k|      TOO_SHORT,
   54|       |      // 1110____ ________ <three byte lead in byte 1>
   55|  12.1k|      TOO_SHORT | OVERLONG_3 | SURROGATE,
   56|       |      // 1111____ ________ <four+ byte lead in byte 1>
   57|  12.1k|      TOO_SHORT | TOO_LARGE | TOO_LARGE_1000 | OVERLONG_4
   58|  12.1k|    );
   59|  12.1k|    constexpr const uint8_t CARRY = TOO_SHORT | TOO_LONG | TWO_CONTS; // These all have ____ in byte 1 .
   60|  12.1k|    const simd8<uint8_t> byte_1_low = (prev1 & 0x0F).lookup_16<uint8_t>(
   61|       |      // ____0000 ________
   62|  12.1k|      CARRY | OVERLONG_3 | OVERLONG_2 | OVERLONG_4,
   63|       |      // ____0001 ________
   64|  12.1k|      CARRY | OVERLONG_2,
   65|       |      // ____001_ ________
   66|  12.1k|      CARRY,
   67|  12.1k|      CARRY,
   68|       |
   69|       |      // ____0100 ________
   70|  12.1k|      CARRY | TOO_LARGE,
   71|       |      // ____0101 ________
   72|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   73|       |      // ____011_ ________
   74|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   75|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   76|       |
   77|       |      // ____1___ ________
   78|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   79|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   80|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   81|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   82|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   83|       |      // ____1101 ________
   84|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000 | SURROGATE,
   85|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000,
   86|  12.1k|      CARRY | TOO_LARGE | TOO_LARGE_1000
   87|  12.1k|    );
   88|  12.1k|    const simd8<uint8_t> byte_2_high = input.shr<4>().lookup_16<uint8_t>(
   89|       |      // ________ 0_______ <ASCII in byte 2>
   90|  12.1k|      TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT,
   91|  12.1k|      TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT,
   92|       |
   93|       |      // ________ 1000____
   94|  12.1k|      TOO_LONG | OVERLONG_2 | TWO_CONTS | OVERLONG_3 | TOO_LARGE_1000 | OVERLONG_4,
   95|       |      // ________ 1001____
   96|  12.1k|      TOO_LONG | OVERLONG_2 | TWO_CONTS | OVERLONG_3 | TOO_LARGE,
   97|       |      // ________ 101_____
   98|  12.1k|      TOO_LONG | OVERLONG_2 | TWO_CONTS | SURROGATE  | TOO_LARGE,
   99|  12.1k|      TOO_LONG | OVERLONG_2 | TWO_CONTS | SURROGATE  | TOO_LARGE,
  100|       |
  101|       |      // ________ 11______
  102|  12.1k|      TOO_SHORT, TOO_SHORT, TOO_SHORT, TOO_SHORT
  103|  12.1k|    );
  104|  12.1k|    return (byte_1_high & byte_1_low & byte_2_high);
  105|  12.1k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation23check_multibyte_lengthsENS1_4simd5simd8IhEES5_S5_:
  107|  12.1k|      const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
  108|  12.1k|    simd8<uint8_t> prev2 = input.prev<2>(prev_input);
  109|  12.1k|    simd8<uint8_t> prev3 = input.prev<3>(prev_input);
  110|  12.1k|    simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
  111|  12.1k|    simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
  112|  12.1k|    return must23_80 ^ sc;
  113|  12.1k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation13is_incompleteENS1_4simd5simd8IhEE:
  119|  6.06k|  simdjson_inline simd8<uint8_t> is_incomplete(const simd8<uint8_t> input) {
  120|       |    // If the previous input's last 3 bytes match this, they're too short (they ended at EOF):
  121|       |    // ... 1111____ 111_____ 11______
  122|  6.06k|#if SIMDJSON_IMPLEMENTATION_ICELAKE
  123|  6.06k|    static const uint8_t max_array[64] = {
  124|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  125|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  126|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  127|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  128|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  129|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  130|  6.06k|      255, 255, 255, 255, 255, 255, 255, 255,
  131|  6.06k|      255, 255, 255, 255, 255, 0xf0u-1, 0xe0u-1, 0xc0u-1
  132|  6.06k|    };
  133|       |#else
  134|       |    static const uint8_t max_array[32] = {
  135|       |      255, 255, 255, 255, 255, 255, 255, 255,
  136|       |      255, 255, 255, 255, 255, 255, 255, 255,
  137|       |      255, 255, 255, 255, 255, 255, 255, 255,
  138|       |      255, 255, 255, 255, 255, 0xf0u-1, 0xe0u-1, 0xc0u-1
  139|       |    };
  140|       |#endif
  141|  6.06k|    const simd8<uint8_t> max_value(&max_array[sizeof(max_array)-sizeof(simd8<uint8_t>)]);
  142|  6.06k|    return input.gt_bits(max_value);
  143|  6.06k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation12utf8_checker9check_eofEv:
  167|  10.5k|    simdjson_inline void check_eof() {
  168|       |      // If the previous block had incomplete UTF-8 characters at the end, an ASCII block can't
  169|       |      // possibly finish them.
  170|  10.5k|      this->error |= this->prev_incomplete;
  171|  10.5k|    }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_115utf8_validation12utf8_checker6errorsEv:
  198|  10.5k|    simdjson_inline error_code errors() {
  199|  10.5k|      return this->error.any_bits_set_anywhere() ? error_code::UTF8_ERROR : error_code::SUCCESS;
  ------------------
  |  Branch (199:14): [True: 564, False: 9.93k]
  ------------------
  200|  10.5k|    }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage213json_iteratorC2ERNS0_25dom_parser_implementationEm:
  245|  9.93k|  : buf{_dom_parser.buf},
  246|  9.93k|    next_structural{&_dom_parser.structural_indexes[start_structural_index]},
  247|  9.93k|    dom_parser{_dom_parser} {
  248|  9.93k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage213json_iterator13walk_documentILb0ENS2_12tape_builderEEENS_10error_codeERT0_:
  119|  9.93k|simdjson_warn_unused simdjson_inline error_code json_iterator::walk_document(V &visitor) noexcept {
  120|  9.93k|  logger::log_start();
  121|       |
  122|       |  //
  123|       |  // Start the document
  124|       |  //
  125|  9.93k|  if (at_eof()) { return EMPTY; }
  ------------------
  |  Branch (125:7): [True: 0, False: 9.93k]
  ------------------
  126|  9.93k|  log_start_value("document");
  127|  9.93k|  SIMDJSON_TRY( visitor.visit_document_start(*this) );
  ------------------
  |  |  273|  9.93k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 9.93k]
  |  |  ------------------
  ------------------
  128|       |
  129|       |  //
  130|       |  // Read first value
  131|       |  //
  132|  9.93k|  {
  133|  9.93k|    auto value = advance();
  134|       |
  135|       |    // Make sure the outer object or array is closed before continuing; otherwise, there are ways we
  136|       |    // could get into memory corruption. See https://github.com/simdjson/simdjson/issues/906
  137|  9.93k|    if (!STREAMING) {
  ------------------
  |  Branch (137:9): [Folded - Ignored]
  ------------------
  138|  9.93k|      switch (*value) {
  ------------------
  |  Branch (138:15): [True: 3.39k, False: 6.54k]
  ------------------
  139|  2.88k|        case '{': if (last_structural() != '}') { log_value("starting brace unmatched"); return TAPE_ERROR; }; break;
  ------------------
  |  Branch (139:9): [True: 2.88k, False: 7.05k]
  |  Branch (139:23): [True: 19, False: 2.86k]
  ------------------
  140|  3.65k|        case '[': if (last_structural() != ']') { log_value("starting bracket unmatched"); return TAPE_ERROR; }; break;
  ------------------
  |  Branch (140:9): [True: 3.65k, False: 6.28k]
  |  Branch (140:23): [True: 25, False: 3.63k]
  ------------------
  141|  9.93k|      }
  142|  9.93k|    }
  143|       |
  144|  9.89k|    switch (*value) {
  145|  2.86k|      case '{': if (*peek() == '}') { advance(); log_value("empty object"); SIMDJSON_TRY( visitor.visit_empty_object(*this) ); break; } goto object_begin;
  ------------------
  |  |  273|      1|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (145:7): [True: 2.86k, False: 7.03k]
  |  Branch (145:21): [True: 1, False: 2.86k]
  ------------------
  146|  3.63k|      case '[': if (*peek() == ']') { advance(); log_value("empty array"); SIMDJSON_TRY( visitor.visit_empty_array(*this) ); break; } goto array_begin;
  ------------------
  |  |  273|      1|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (146:7): [True: 3.63k, False: 6.26k]
  |  Branch (146:21): [True: 1, False: 3.63k]
  ------------------
  147|  3.63k|      default: SIMDJSON_TRY( visitor.visit_root_primitive(*this, value) ); break;
  ------------------
  |  |  273|  3.39k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 976, False: 2.42k]
  |  |  ------------------
  ------------------
  |  Branch (147:7): [True: 3.39k, False: 6.49k]
  ------------------
  148|  9.89k|    }
  149|  9.89k|  }
  150|  2.42k|  goto document_end;
  151|       |
  152|       |//
  153|       |// Object parser states
  154|       |//
  155|  11.9k|object_begin:
  156|  11.9k|  log_start_value("object");
  157|  11.9k|  depth++;
  158|  11.9k|  if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
  ------------------
  |  Branch (158:7): [True: 1, False: 11.9k]
  ------------------
  159|  11.9k|  dom_parser.is_array[depth] = false;
  160|  11.9k|  SIMDJSON_TRY( visitor.visit_object_start(*this) );
  ------------------
  |  |  273|  11.9k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 11.9k]
  |  |  ------------------
  ------------------
  161|       |
  162|  11.9k|  {
  163|  11.9k|    auto key = advance();
  164|  11.9k|    if (*key != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
  ------------------
  |  Branch (164:9): [True: 60, False: 11.8k]
  ------------------
  165|  11.8k|    SIMDJSON_TRY( visitor.increment_count(*this) );
  ------------------
  |  |  273|  11.8k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 11.8k]
  |  |  ------------------
  ------------------
  166|  11.8k|    SIMDJSON_TRY( visitor.visit_key(*this, key) );
  ------------------
  |  |  273|  11.8k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 95, False: 11.7k]
  |  |  ------------------
  ------------------
  167|  11.7k|  }
  168|       |
  169|   246k|object_field:
  170|   246k|  if (simdjson_unlikely( *advance() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
  ------------------
  |  |  106|   246k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 454, False: 246k]
  |  |  ------------------
  ------------------
  171|   246k|  {
  172|   246k|    auto value = advance();
  173|   246k|    switch (*value) {
  174|  2.24k|      case '{': if (*peek() == '}') { advance(); log_value("empty object"); SIMDJSON_TRY( visitor.visit_empty_object(*this) ); break; } goto object_begin;
  ------------------
  |  |  273|  1.09k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 1.09k]
  |  |  ------------------
  ------------------
  |  Branch (174:7): [True: 2.24k, False: 244k]
  |  Branch (174:21): [True: 1.09k, False: 1.14k]
  ------------------
  175|  6.84k|      case '[': if (*peek() == ']') { advance(); log_value("empty array"); SIMDJSON_TRY( visitor.visit_empty_array(*this) ); break; } goto array_begin;
  ------------------
  |  |  273|  5.74k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 5.74k]
  |  |  ------------------
  ------------------
  |  Branch (175:7): [True: 6.84k, False: 239k]
  |  Branch (175:21): [True: 5.74k, False: 1.09k]
  ------------------
  176|   237k|      default: SIMDJSON_TRY( visitor.visit_primitive(*this, value) ); break;
  ------------------
  |  |  273|   237k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 610, False: 236k]
  |  |  ------------------
  ------------------
  |  Branch (176:7): [True: 237k, False: 9.08k]
  ------------------
  177|   246k|    }
  178|   246k|  }
  179|       |
  180|   245k|object_continue:
  181|   245k|  switch (*advance()) {
  182|   235k|    case ',':
  ------------------
  |  Branch (182:5): [True: 235k, False: 9.82k]
  ------------------
  183|   235k|      SIMDJSON_TRY( visitor.increment_count(*this) );
  ------------------
  |  |  273|   235k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 235k]
  |  |  ------------------
  ------------------
  184|   235k|      {
  185|   235k|        auto key = advance();
  186|   235k|        if (simdjson_unlikely( *key != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
  ------------------
  |  |  106|   235k|  #define simdjson_unlikely(x) __builtin_expect(!!(x), 0)
  |  |  ------------------
  |  |  |  Branch (106:32): [True: 19, False: 235k]
  |  |  ------------------
  ------------------
  187|   235k|        SIMDJSON_TRY( visitor.visit_key(*this, key) );
  ------------------
  |  |  273|   235k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 80, False: 235k]
  |  |  ------------------
  ------------------
  188|   235k|      }
  189|      0|      goto object_field;
  190|  9.72k|    case '}': log_end_value("object"); SIMDJSON_TRY( visitor.visit_object_end(*this) ); goto scope_end;
  ------------------
  |  |  273|  9.72k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 9.72k]
  |  |  ------------------
  ------------------
  |  Branch (190:5): [True: 9.72k, False: 235k]
  ------------------
  191|    101|    default: log_error("No comma between object fields"); return TAPE_ERROR;
  ------------------
  |  Branch (191:5): [True: 101, False: 244k]
  ------------------
  192|   245k|  }
  193|       |
  194|  73.5k|scope_end:
  195|  73.5k|  depth--;
  196|  73.5k|  if (depth == 0) { goto document_end; }
  ------------------
  |  Branch (196:7): [True: 4.20k, False: 69.3k]
  ------------------
  197|  69.3k|  if (dom_parser.is_array[depth]) { goto array_continue; }
  ------------------
  |  Branch (197:7): [True: 67.8k, False: 1.45k]
  ------------------
  198|  1.45k|  goto object_continue;
  199|       |
  200|       |//
  201|       |// Array parser states
  202|       |//
  203|  77.4k|array_begin:
  204|  77.4k|  log_start_value("array");
  205|  77.4k|  depth++;
  206|  77.4k|  if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
  ------------------
  |  Branch (206:7): [True: 1, False: 77.4k]
  ------------------
  207|  77.4k|  dom_parser.is_array[depth] = true;
  208|  77.4k|  SIMDJSON_TRY( visitor.visit_array_start(*this) );
  ------------------
  |  |  273|  77.4k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 77.4k]
  |  |  ------------------
  ------------------
  209|  77.4k|  SIMDJSON_TRY( visitor.increment_count(*this) );
  ------------------
  |  |  273|  77.4k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 77.4k]
  |  |  ------------------
  ------------------
  210|       |
  211|  4.98M|array_value:
  212|  4.98M|  {
  213|  4.98M|    auto value = advance();
  214|  4.98M|    switch (*value) {
  215|  9.67k|      case '{': if (*peek() == '}') { advance(); log_value("empty object"); SIMDJSON_TRY( visitor.visit_empty_object(*this) ); break; } goto object_begin;
  ------------------
  |  |  273|  1.75k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 1.75k]
  |  |  ------------------
  ------------------
  |  Branch (215:7): [True: 9.67k, False: 4.97M]
  |  Branch (215:21): [True: 1.75k, False: 7.91k]
  ------------------
  216|  74.6k|      case '[': if (*peek() == ']') { advance(); log_value("empty array"); SIMDJSON_TRY( visitor.visit_empty_array(*this) ); break; } goto array_begin;
  ------------------
  |  |  273|  1.98k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 1.98k]
  |  |  ------------------
  ------------------
  |  Branch (216:7): [True: 74.6k, False: 4.90M]
  |  Branch (216:21): [True: 1.98k, False: 72.6k]
  ------------------
  217|  4.89M|      default: SIMDJSON_TRY( visitor.visit_primitive(*this, value) ); break;
  ------------------
  |  |  273|  4.89M|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 761, False: 4.89M]
  |  |  ------------------
  ------------------
  |  Branch (217:7): [True: 4.89M, False: 84.3k]
  ------------------
  218|  4.98M|    }
  219|  4.98M|  }
  220|       |
  221|  4.97M|array_continue:
  222|  4.97M|  switch (*advance()) {
  223|  4.90M|    case ',': SIMDJSON_TRY( visitor.increment_count(*this) ); goto array_value;
  ------------------
  |  |  273|  4.90M|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 4.90M]
  |  |  ------------------
  ------------------
  |  Branch (223:5): [True: 4.90M, False: 63.8k]
  ------------------
  224|  63.7k|    case ']': log_end_value("array"); SIMDJSON_TRY( visitor.visit_array_end(*this) ); goto scope_end;
  ------------------
  |  |  273|  63.7k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 63.7k]
  |  |  ------------------
  ------------------
  |  Branch (224:5): [True: 63.7k, False: 4.90M]
  ------------------
  225|    105|    default: log_error("Missing comma between array values"); return TAPE_ERROR;
  ------------------
  |  Branch (225:5): [True: 105, False: 4.97M]
  ------------------
  226|  4.97M|  }
  227|       |
  228|  6.63k|document_end:
  229|  6.63k|  log_end_value("document");
  230|  6.63k|  SIMDJSON_TRY( visitor.visit_document_end(*this) );
  ------------------
  |  |  273|  6.63k|#define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } }
  |  |  ------------------
  |  |  |  Branch (273:54): [True: 0, False: 6.63k]
  |  |  ------------------
  ------------------
  231|       |
  232|  6.63k|  dom_parser.next_structural_index = uint32_t(next_structural - &dom_parser.structural_indexes[0]);
  233|       |
  234|       |  // If we didn't make it to the end, it's an error
  235|  6.63k|  if ( !STREAMING && dom_parser.next_structural_index != dom_parser.n_structural_indexes ) {
  ------------------
  |  Branch (235:8): [Folded - Ignored]
  |  Branch (235:22): [True: 47, False: 6.58k]
  ------------------
  236|     47|    log_error("More than one JSON value at the root of the document, or extra characters at the end of the JSON!");
  237|     47|    return TAPE_ERROR;
  238|     47|  }
  239|       |
  240|  6.58k|  return SUCCESS;
  241|       |
  242|  6.63k|} // walk_document()
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator6at_eofEv:
  260|  9.93k|simdjson_inline bool json_iterator::at_eof() const noexcept {
  261|  9.93k|  return next_structural == &dom_parser.structural_indexes[dom_parser.n_structural_indexes];
  262|  9.93k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator15log_start_valueEPKc:
  274|  99.2k|simdjson_inline void json_iterator::log_start_value(const char *type) const noexcept {
  275|  99.2k|  logger::log_line(*this, "+", type, "");
  276|  99.2k|  if (logger::LOG_ENABLED) { logger::log_depth++; }
  ------------------
  |  Branch (276:7): [Folded - Ignored]
  ------------------
  277|  99.2k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage213json_iterator7advanceEv:
  253|  10.9M|simdjson_inline const uint8_t *json_iterator::advance() noexcept {
  254|  10.9M|  return &buf[*(next_structural++)];
  255|  10.9M|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator15last_structuralEv:
  266|  6.54k|simdjson_inline uint8_t json_iterator::last_structural() const noexcept {
  267|  6.54k|  return buf[dom_parser.structural_indexes[dom_parser.n_structural_indexes - 1]];
  268|  6.54k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator9log_valueEPKc:
  270|  5.39M|simdjson_inline void json_iterator::log_value(const char *type) const noexcept {
  271|  5.39M|  logger::log_line(*this, "", type, "");
  272|  5.39M|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator4peekEv:
  250|  99.9k|simdjson_inline const uint8_t *json_iterator::peek() const noexcept {
  251|  99.9k|  return &buf[*(next_structural)];
  252|  99.9k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage213json_iterator20visit_root_primitiveINS2_12tape_builderEEENS_10error_codeERT_PKh:
  289|  3.39k|simdjson_warn_unused simdjson_inline error_code json_iterator::visit_root_primitive(V &visitor, const uint8_t *value) noexcept {
  290|  3.39k|  switch (*value) {
  291|    377|    case '"': return visitor.visit_root_string(*this, value);
  ------------------
  |  Branch (291:5): [True: 377, False: 3.02k]
  ------------------
  292|     42|    case 't': return visitor.visit_root_true_atom(*this, value);
  ------------------
  |  Branch (292:5): [True: 42, False: 3.35k]
  ------------------
  293|     98|    case 'f': return visitor.visit_root_false_atom(*this, value);
  ------------------
  |  Branch (293:5): [True: 98, False: 3.30k]
  ------------------
  294|     40|    case 'n': return visitor.visit_root_null_atom(*this, value);
  ------------------
  |  Branch (294:5): [True: 40, False: 3.35k]
  ------------------
  295|    195|    case '-':
  ------------------
  |  Branch (295:5): [True: 195, False: 3.20k]
  ------------------
  296|  1.27k|    case '0': case '1': case '2': case '3': case '4':
  ------------------
  |  Branch (296:5): [True: 162, False: 3.23k]
  |  Branch (296:15): [True: 347, False: 3.05k]
  |  Branch (296:25): [True: 259, False: 3.14k]
  |  Branch (296:35): [True: 127, False: 3.27k]
  |  Branch (296:45): [True: 183, False: 3.21k]
  ------------------
  297|  2.73k|    case '5': case '6': case '7': case '8': case '9':
  ------------------
  |  Branch (297:5): [True: 155, False: 3.24k]
  |  Branch (297:15): [True: 138, False: 3.26k]
  |  Branch (297:25): [True: 170, False: 3.22k]
  |  Branch (297:35): [True: 265, False: 3.13k]
  |  Branch (297:45): [True: 733, False: 2.66k]
  ------------------
  298|  2.73k|      return visitor.visit_root_number(*this, value);
  299|    108|    default:
  ------------------
  |  Branch (299:5): [True: 108, False: 3.29k]
  ------------------
  300|    108|      log_error("Document starts with a non-value character");
  301|    108|      return TAPE_ERROR;
  302|  3.39k|  }
  303|  3.39k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator13remaining_lenEv:
  256|  8.38k|simdjson_inline size_t json_iterator::remaining_len() const noexcept {
  257|  8.38k|  return dom_parser.len - *(next_structural-1);
  258|  8.38k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator9log_errorEPKc:
  284|  1.38k|simdjson_inline void json_iterator::log_error(const char *error) const noexcept {
  285|  1.38k|  logger::log_line(*this, "", "ERROR", error);
  286|  1.38k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage213json_iterator15visit_primitiveINS2_12tape_builderEEENS_10error_codeERT_PKh:
  305|  5.13M|simdjson_warn_unused simdjson_inline error_code json_iterator::visit_primitive(V &visitor, const uint8_t *value) noexcept {
  306|       |  // Use the fact that most scalars are going to be either strings or numbers.
  307|  5.13M|  if(*value == '"') {
  ------------------
  |  Branch (307:6): [True: 3.95k, False: 5.13M]
  ------------------
  308|  3.95k|    return visitor.visit_string(*this, value);
  309|  5.13M|  } else if (((*value - '0')  < 10) || (*value == '-')) {
  ------------------
  |  Branch (309:14): [True: 5.13M, False: 1.50k]
  |  Branch (309:40): [True: 0, False: 1.50k]
  ------------------
  310|  5.13M|    return visitor.visit_number(*this, value);
  311|  5.13M|  }
  312|       |  // true, false, null are uncommon.
  313|  1.50k|  switch (*value) {
  314|    491|    case 't': return visitor.visit_true_atom(*this, value);
  ------------------
  |  Branch (314:5): [True: 491, False: 1.01k]
  ------------------
  315|    487|    case 'f': return visitor.visit_false_atom(*this, value);
  ------------------
  |  Branch (315:5): [True: 487, False: 1.01k]
  ------------------
  316|    463|    case 'n': return visitor.visit_null_atom(*this, value);
  ------------------
  |  Branch (316:5): [True: 463, False: 1.03k]
  ------------------
  317|     60|    default:
  ------------------
  |  Branch (317:5): [True: 60, False: 1.44k]
  ------------------
  318|     60|      log_error("Non-value found when value was expected!");
  319|     60|      return TAPE_ERROR;
  320|  1.50k|  }
  321|  1.50k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage213json_iterator13log_end_valueEPKc:
  279|  80.1k|simdjson_inline void json_iterator::log_end_value(const char *type) const noexcept {
  280|  80.1k|  if (logger::LOG_ENABLED) { logger::log_depth--; }
  ------------------
  |  Branch (280:7): [Folded - Ignored]
  ------------------
  281|  80.1k|  logger::log_line(*this, "-", type, "");
  282|  80.1k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16logger9log_startEv:
   42|  9.93k|  static simdjson_inline void log_start() {
   43|  9.93k|    if (LOG_ENABLED) {
  ------------------
  |  Branch (43:9): [Folded - Ignored]
  ------------------
   44|      0|      log_depth = 0;
   45|      0|      printf("\n");
   46|      0|      printf("| %-*s | %-*s | %-*s | %-*s | Detail |\n", LOG_EVENT_LEN, "Event", LOG_BUFFER_LEN, "Buffer", LOG_SMALL_BUFFER_LEN, "Next", 5, "Next#");
   47|      0|      printf("|%.*s|%.*s|%.*s|%.*s|--------|\n", LOG_EVENT_LEN+2, DASHES, LOG_BUFFER_LEN+2, DASHES, LOG_SMALL_BUFFER_LEN+2, DASHES, 5+2, DASHES);
   48|      0|    }
   49|  9.93k|  }
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16logger8log_lineIKNS1_6stage213json_iteratorEEEvRT_PKcSA_SA_:
   59|  5.57M|  static simdjson_inline void log_line(S &structurals, const char *title_prefix, const char *title, const char *detail) {
   60|  5.57M|    if (LOG_ENABLED) {
  ------------------
  |  Branch (60:9): [Folded - Ignored]
  ------------------
   61|      0|      printf("| %*s%s%-*s ", log_depth*2, "", title_prefix, LOG_EVENT_LEN - log_depth*2 - int(strlen(title_prefix)), title);
   62|      0|      auto current_index = structurals.at_beginning() ? nullptr : structurals.next_structural-1;
  ------------------
  |  Branch (62:28): [True: 0, False: 0]
  ------------------
   63|      0|      auto next_index = structurals.next_structural;
   64|      0|      auto current = current_index ? &structurals.buf[*current_index] : reinterpret_cast<const uint8_t*>("                                                       ");
  ------------------
  |  Branch (64:22): [True: 0, False: 0]
  ------------------
   65|      0|      auto next = &structurals.buf[*next_index];
   66|      0|      {
   67|       |        // Print the next N characters in the buffer.
   68|      0|        printf("| ");
   69|       |        // Otherwise, print the characters starting from the buffer position.
   70|       |        // Print spaces for unprintable or newline characters.
   71|      0|        for (int i=0;i<LOG_BUFFER_LEN;i++) {
  ------------------
  |  Branch (71:22): [True: 0, False: 0]
  ------------------
   72|      0|          printf("%c", printable_char(current[i]));
   73|      0|        }
   74|      0|        printf(" ");
   75|       |        // Print the next N characters in the buffer.
   76|      0|        printf("| ");
   77|       |        // Otherwise, print the characters starting from the buffer position.
   78|       |        // Print spaces for unprintable or newline characters.
   79|      0|        for (int i=0;i<LOG_SMALL_BUFFER_LEN;i++) {
  ------------------
  |  Branch (79:22): [True: 0, False: 0]
  ------------------
   80|      0|          printf("%c", printable_char(next[i]));
   81|      0|        }
   82|      0|        printf(" ");
   83|      0|      }
   84|      0|      if (current_index) {
  ------------------
  |  Branch (84:11): [True: 0, False: 0]
  ------------------
   85|      0|        printf("| %*u ", LOG_INDEX_LEN, *current_index);
   86|      0|      } else {
   87|      0|        printf("| %-*s ", LOG_INDEX_LEN, "");
   88|      0|      }
   89|       |      // printf("| %*u ", LOG_INDEX_LEN, structurals.next_tape_index());
   90|      0|      printf("| %-s ", detail);
   91|      0|      printf("|\n");
   92|      0|    }
   93|  5.57M|  }

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_113stringparsing12parse_stringEPKhPhb:
  150|   251k|simdjson_warn_unused simdjson_inline uint8_t *parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) {
  151|  1.13M|  while (1) {
  ------------------
  |  Branch (151:10): [Folded - Ignored]
  ------------------
  152|       |    // Copy the next n bytes, and find the backslash and quote in them.
  153|  1.13M|    auto bs_quote = backslash_and_quote::copy_and_find(src, dst);
  154|       |    // If the next thing is the end quote, copy and return
  155|  1.13M|    if (bs_quote.has_quote_first()) {
  ------------------
  |  Branch (155:9): [True: 250k, False: 887k]
  ------------------
  156|       |      // we encountered quotes first. Move dst to point to quotes and exit
  157|   250k|      return dst + bs_quote.quote_index();
  158|   250k|    }
  159|   887k|    if (bs_quote.has_backslash()) {
  ------------------
  |  Branch (159:9): [True: 43.9k, False: 843k]
  ------------------
  160|       |      /* find out where the backspace is */
  161|  43.9k|      auto bs_dist = bs_quote.backslash_index();
  162|  43.9k|      uint8_t escape_char = src[bs_dist + 1];
  163|       |      /* we encountered backslash first. Handle backslash */
  164|  43.9k|      if (escape_char == 'u') {
  ------------------
  |  Branch (164:11): [True: 10.7k, False: 33.2k]
  ------------------
  165|       |        /* move src/dst up to the start; they will be further adjusted
  166|       |           within the unicode codepoint handling code. */
  167|  10.7k|        src += bs_dist;
  168|  10.7k|        dst += bs_dist;
  169|  10.7k|        if (!handle_unicode_codepoint(&src, &dst, allow_replacement)) {
  ------------------
  |  Branch (169:13): [True: 332, False: 10.3k]
  ------------------
  170|    332|          return nullptr;
  171|    332|        }
  172|  33.2k|      } else {
  173|       |        /* simple 1:1 conversion. Will eat bs_dist+2 characters in input and
  174|       |         * write bs_dist+1 characters to output
  175|       |         * note this may reach beyond the part of the buffer we've actually
  176|       |         * seen. I think this is ok */
  177|  33.2k|        uint8_t escape_result = escape_map[escape_char];
  178|  33.2k|        if (escape_result == 0u) {
  ------------------
  |  Branch (178:13): [True: 101, False: 33.1k]
  ------------------
  179|    101|          return nullptr; /* bogus escape value is an error */
  180|    101|        }
  181|  33.1k|        dst[bs_dist] = escape_result;
  182|  33.1k|        src += bs_dist + 2;
  183|  33.1k|        dst += bs_dist + 1;
  184|  33.1k|      }
  185|   843k|    } else {
  186|       |      /* they are the same. Since they can't co-occur, it means we
  187|       |       * encountered neither. */
  188|   843k|      src += backslash_and_quote::BYTES_PROCESSED;
  189|   843k|      dst += backslash_and_quote::BYTES_PROCESSED;
  190|   843k|    }
  191|   887k|  }
  192|   251k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_113stringparsing24handle_unicode_codepointEPPKhPPhb:
   52|  10.7k|                                            uint8_t **dst_ptr, bool allow_replacement) {
   53|       |  // Use the default Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD)
   54|  10.7k|  constexpr uint32_t substitution_code_point = 0xfffd;
   55|       |  // jsoncharutils::hex_to_u32_nocheck fills high 16 bits of the return value with 1s if the
   56|       |  // conversion is not valid; we defer the check for this to inside the
   57|       |  // multilingual plane check.
   58|  10.7k|  uint32_t code_point = jsoncharutils::hex_to_u32_nocheck(*src_ptr + 2);
   59|  10.7k|  *src_ptr += 6;
   60|       |
   61|       |  // If we found a high surrogate, we must
   62|       |  // check for low surrogate for characters
   63|       |  // outside the Basic
   64|       |  // Multilingual Plane.
   65|  10.7k|  if (code_point >= 0xd800 && code_point < 0xdc00) {
  ------------------
  |  Branch (65:7): [True: 6.88k, False: 3.83k]
  |  Branch (65:31): [True: 1.42k, False: 5.45k]
  ------------------
   66|  1.42k|    const uint8_t *src_data = *src_ptr;
   67|       |    /* Compiler optimizations convert this to a single 16-bit load and compare on most platforms */
   68|  1.42k|    if (((src_data[0] << 8) | src_data[1]) != ((static_cast<uint8_t> ('\\') << 8) | static_cast<uint8_t> ('u'))) {
  ------------------
  |  Branch (68:9): [True: 146, False: 1.28k]
  ------------------
   69|    146|      if(!allow_replacement) { return false; }
  ------------------
  |  Branch (69:10): [True: 146, False: 0]
  ------------------
   70|      0|      code_point = substitution_code_point;
   71|  1.28k|    } else {
   72|  1.28k|      uint32_t code_point_2 = jsoncharutils::hex_to_u32_nocheck(src_data + 2);
   73|       |
   74|       |      // We have already checked that the high surrogate is valid and
   75|       |      // (code_point - 0xd800) < 1024.
   76|       |      //
   77|       |      // Check that code_point_2 is in the range 0xdc00..0xdfff
   78|       |      // and that code_point_2 was parsed from valid hex.
   79|  1.28k|      uint32_t low_bit = code_point_2 - 0xdc00;
   80|  1.28k|      if (low_bit >> 10) {
  ------------------
  |  Branch (80:11): [True: 88, False: 1.19k]
  ------------------
   81|     88|        if(!allow_replacement) { return false; }
  ------------------
  |  Branch (81:12): [True: 88, False: 0]
  ------------------
   82|      0|        code_point = substitution_code_point;
   83|  1.19k|      } else {
   84|  1.19k|        code_point =  (((code_point - 0xd800) << 10) | low_bit) + 0x10000;
   85|  1.19k|        *src_ptr += 6;
   86|  1.19k|      }
   87|       |
   88|  1.28k|    }
   89|  9.28k|  } else if (code_point >= 0xdc00 && code_point <= 0xdfff) {
  ------------------
  |  Branch (89:14): [True: 5.45k, False: 3.83k]
  |  Branch (89:38): [True: 51, False: 5.40k]
  ------------------
   90|       |      // If we encounter a low surrogate (not preceded by a high surrogate)
   91|       |      // then we have an error.
   92|     51|      if(!allow_replacement) { return false; }
  ------------------
  |  Branch (92:10): [True: 51, False: 0]
  ------------------
   93|      0|      code_point = substitution_code_point;
   94|      0|  }
   95|  10.4k|  size_t offset = jsoncharutils::codepoint_to_utf8(code_point, *dst_ptr);
   96|  10.4k|  *dst_ptr += offset;
   97|  10.4k|  return offset > 0;
   98|  10.7k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder14parse_documentILb0EEENS_10error_codeERNS0_25dom_parser_implementationERNS_3dom8documentE:
  101|  9.93k|    dom::document &doc) noexcept {
  102|  9.93k|  dom_parser.doc = &doc;
  103|  9.93k|  json_iterator iter(dom_parser, STREAMING ? dom_parser.next_structural_index : 0);
  ------------------
  |  Branch (103:34): [Folded - Ignored]
  ------------------
  104|  9.93k|  tape_builder builder(doc);
  105|  9.93k|  return iter.walk_document<STREAMING>(builder);
  106|  9.93k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builderC2ERNS_3dom8documentE:
  155|  9.93k|simdjson_inline tape_builder::tape_builder(dom::document &doc) noexcept : tape{doc.tape.get()}, current_string_buf_loc{doc.string_buf.get()} {}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder20visit_document_startERNS2_13json_iteratorE:
  121|  9.93k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_document_start(json_iterator &iter) noexcept {
  122|  9.93k|  start_container(iter);
  123|  9.93k|  return SUCCESS;
  124|  9.93k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15start_containerERNS2_13json_iteratorE:
  255|  99.2k|simdjson_inline void tape_builder::start_container(json_iterator &iter) noexcept {
  256|  99.2k|  iter.dom_parser.open_containers[iter.depth].tape_index = next_tape_index(iter);
  257|  99.2k|  iter.dom_parser.open_containers[iter.depth].count = 0;
  258|  99.2k|  tape.skip(); // We don't actually *write* the start element until the end.
  259|  99.2k|}
simdjson.cpp:_ZNK8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15next_tape_indexERNS2_13json_iteratorE:
  244|   190k|simdjson_inline uint32_t tape_builder::next_tape_index(json_iterator &iter) const noexcept {
  245|   190k|  return uint32_t(tape.next_tape_loc - iter.dom_parser.doc->tape.get());
  246|   190k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder18visit_empty_objectERNS2_13json_iteratorE:
  114|  2.84k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_empty_object(json_iterator &iter) noexcept {
  115|  2.84k|  return empty_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT);
  116|  2.84k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15empty_containerERNS2_13json_iteratorENS_8internal9tape_typeES7_:
  248|  10.5k|simdjson_warn_unused simdjson_inline error_code tape_builder::empty_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept {
  249|  10.5k|  auto start_index = next_tape_index(iter);
  250|  10.5k|  tape.append(start_index+2, start);
  251|  10.5k|  tape.append(start_index, end);
  252|  10.5k|  return SUCCESS;
  253|  10.5k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder17visit_empty_arrayERNS2_13json_iteratorE:
  117|  7.73k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_empty_array(json_iterator &iter) noexcept {
  118|  7.73k|  return empty_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY);
  119|  7.73k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder20visit_root_primitiveERNS2_13json_iteratorEPKh:
  108|  3.39k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_primitive(json_iterator &iter, const uint8_t *value) noexcept {
  109|  3.39k|  return iter.visit_root_primitive(*this, value);
  110|  3.39k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder17visit_root_stringERNS2_13json_iteratorEPKh:
  169|    377|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(json_iterator &iter, const uint8_t *value) noexcept {
  170|    377|  return visit_string(iter, value);
  171|    377|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder12visit_stringERNS2_13json_iteratorEPKhb:
  157|   251k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_string(json_iterator &iter, const uint8_t *value, bool key) noexcept {
  158|   251k|  iter.log_value(key ? "key" : "string");
  ------------------
  |  Branch (158:18): [True: 247k, False: 4.33k]
  ------------------
  159|   251k|  uint8_t *dst = on_start_string(iter);
  160|   251k|  dst = stringparsing::parse_string(value+1, dst, false); // We do not allow replacement when the escape characters are invalid.
  161|   251k|  if (dst == nullptr) {
  ------------------
  |  Branch (161:7): [True: 433, False: 250k]
  ------------------
  162|    433|    iter.log_error("Invalid escape in string");
  163|    433|    return STRING_ERROR;
  164|    433|  }
  165|   250k|  on_end_string(dst);
  166|   250k|  return SUCCESS;
  167|   251k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15on_start_stringERNS2_13json_iteratorE:
  274|   251k|simdjson_inline uint8_t *tape_builder::on_start_string(json_iterator &iter) noexcept {
  275|       |  // we advance the point, accounting for the fact that we have a NULL termination
  276|   251k|  tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::STRING);
  277|   251k|  return current_string_buf_loc + sizeof(uint32_t);
  278|   251k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder13on_end_stringEPh:
  280|   250k|simdjson_inline void tape_builder::on_end_string(uint8_t *dst) noexcept {
  281|   250k|  uint32_t str_length = uint32_t(dst - (current_string_buf_loc + sizeof(uint32_t)));
  282|       |  // TODO check for overflow in case someone has a crazy string (>=4GB?)
  283|       |  // But only add the overflow check when the document itself exceeds 4GB
  284|       |  // Currently unneeded because we refuse to parse docs larger or equal to 4GB.
  285|   250k|  memcpy(current_string_buf_loc, &str_length, sizeof(uint32_t));
  286|       |  // NULL termination is still handy if you expect all your strings to
  287|       |  // be NULL terminated? It comes at a small cost
  288|   250k|  *dst = 0;
  289|   250k|  current_string_buf_loc = dst + 1;
  290|   250k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder20visit_root_true_atomERNS2_13json_iteratorEPKh:
  207|     42|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_true_atom(json_iterator &iter, const uint8_t *value) noexcept {
  208|     42|  iter.log_value("true");
  209|     42|  if (!atomparsing::is_valid_true_atom(value, iter.remaining_len())) { return T_ATOM_ERROR; }
  ------------------
  |  Branch (209:7): [True: 40, False: 2]
  ------------------
  210|      2|  tape.append(0, internal::tape_type::TRUE_VALUE);
  211|      2|  return SUCCESS;
  212|     42|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder21visit_root_false_atomERNS2_13json_iteratorEPKh:
  221|     98|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_false_atom(json_iterator &iter, const uint8_t *value) noexcept {
  222|     98|  iter.log_value("false");
  223|     98|  if (!atomparsing::is_valid_false_atom(value, iter.remaining_len())) { return F_ATOM_ERROR; }
  ------------------
  |  Branch (223:7): [True: 96, False: 2]
  ------------------
  224|      2|  tape.append(0, internal::tape_type::FALSE_VALUE);
  225|      2|  return SUCCESS;
  226|     98|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder20visit_root_null_atomERNS2_13json_iteratorEPKh:
  235|     40|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_null_atom(json_iterator &iter, const uint8_t *value) noexcept {
  236|     40|  iter.log_value("null");
  237|     40|  if (!atomparsing::is_valid_null_atom(value, iter.remaining_len())) { return N_ATOM_ERROR; }
  ------------------
  |  Branch (237:7): [True: 39, False: 1]
  ------------------
  238|      1|  tape.append(0, internal::tape_type::NULL_VALUE);
  239|      1|  return SUCCESS;
  240|     40|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder17visit_root_numberERNS2_13json_iteratorEPKh:
  178|  2.73k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
  179|       |  //
  180|       |  // We need to make a copy to make sure that the string is space terminated.
  181|       |  // This is not about padding the input, which should already padded up
  182|       |  // to len + SIMDJSON_PADDING. However, we have no control at this stage
  183|       |  // on how the padding was done. What if the input string was padded with nulls?
  184|       |  // It is quite common for an input string to have an extra null character (C string).
  185|       |  // We do not want to allow 9\0 (where \0 is the null character) inside a JSON
  186|       |  // document, but the string "9\0" by itself is fine. So we make a copy and
  187|       |  // pad the input with spaces when we know that there is just one input element.
  188|       |  // This copy is relatively expensive, but it will almost never be called in
  189|       |  // practice unless you are in the strange scenario where you have many JSON
  190|       |  // documents made of single atoms.
  191|       |  //
  192|  2.73k|  std::unique_ptr<uint8_t[]>copy(new (std::nothrow) uint8_t[iter.remaining_len() + SIMDJSON_PADDING]);
  193|  2.73k|  if (copy.get() == nullptr) { return MEMALLOC; }
  ------------------
  |  Branch (193:7): [True: 0, False: 2.73k]
  ------------------
  194|  2.73k|  std::memcpy(copy.get(), value, iter.remaining_len());
  195|  2.73k|  std::memset(copy.get() + iter.remaining_len(), ' ', SIMDJSON_PADDING);
  196|  2.73k|  error_code error = visit_number(iter, copy.get());
  197|  2.73k|  return error;
  198|  2.73k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder12visit_numberERNS2_13json_iteratorEPKh:
  173|  5.13M|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
  174|  5.13M|  iter.log_value("number");
  175|  5.13M|  return numberparsing::parse_number(value, tape);
  176|  5.13M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder18visit_object_startERNS2_13json_iteratorE:
  125|  11.9k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_object_start(json_iterator &iter) noexcept {
  126|  11.9k|  start_container(iter);
  127|  11.9k|  return SUCCESS;
  128|  11.9k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15increment_countERNS2_13json_iteratorE:
  150|  5.23M|simdjson_warn_unused simdjson_inline error_code tape_builder::increment_count(json_iterator &iter) noexcept {
  151|  5.23M|  iter.dom_parser.open_containers[iter.depth].count++; // we have a key value pair in the object at parser.dom_parser.depth - 1
  152|  5.23M|  return SUCCESS;
  153|  5.23M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder9visit_keyERNS2_13json_iteratorEPKh:
  146|   247k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_key(json_iterator &iter, const uint8_t *key) noexcept {
  147|   247k|  return visit_string(iter, key, true);
  148|   247k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15visit_primitiveERNS2_13json_iteratorEPKh:
  111|  5.13M|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_primitive(json_iterator &iter, const uint8_t *value) noexcept {
  112|  5.13M|  return iter.visit_primitive(*this, value);
  113|  5.13M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15visit_true_atomERNS2_13json_iteratorEPKh:
  200|    491|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_true_atom(json_iterator &iter, const uint8_t *value) noexcept {
  201|    491|  iter.log_value("true");
  202|    491|  if (!atomparsing::is_valid_true_atom(value)) { return T_ATOM_ERROR; }
  ------------------
  |  Branch (202:7): [True: 73, False: 418]
  ------------------
  203|    418|  tape.append(0, internal::tape_type::TRUE_VALUE);
  204|    418|  return SUCCESS;
  205|    491|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder16visit_false_atomERNS2_13json_iteratorEPKh:
  214|    487|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_false_atom(json_iterator &iter, const uint8_t *value) noexcept {
  215|    487|  iter.log_value("false");
  216|    487|  if (!atomparsing::is_valid_false_atom(value)) { return F_ATOM_ERROR; }
  ------------------
  |  Branch (216:7): [True: 98, False: 389]
  ------------------
  217|    389|  tape.append(0, internal::tape_type::FALSE_VALUE);
  218|    389|  return SUCCESS;
  219|    487|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15visit_null_atomERNS2_13json_iteratorEPKh:
  228|    463|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_null_atom(json_iterator &iter, const uint8_t *value) noexcept {
  229|    463|  iter.log_value("null");
  230|    463|  if (!atomparsing::is_valid_null_atom(value)) { return N_ATOM_ERROR; }
  ------------------
  |  Branch (230:7): [True: 72, False: 391]
  ------------------
  231|    391|  tape.append(0, internal::tape_type::NULL_VALUE);
  232|    391|  return SUCCESS;
  233|    463|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder16visit_object_endERNS2_13json_iteratorE:
  134|  9.72k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_object_end(json_iterator &iter) noexcept {
  135|  9.72k|  return end_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT);
  136|  9.72k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder13end_containerERNS2_13json_iteratorENS_8internal9tape_typeES7_:
  261|  73.5k|simdjson_warn_unused simdjson_inline error_code tape_builder::end_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept {
  262|       |  // Write the ending tape element, pointing at the start location
  263|  73.5k|  const uint32_t start_tape_index = iter.dom_parser.open_containers[iter.depth].tape_index;
  264|  73.5k|  tape.append(start_tape_index, end);
  265|       |  // Write the start tape element, pointing at the end location (and including count)
  266|       |  // count can overflow if it exceeds 24 bits... so we saturate
  267|       |  // the convention being that a cnt of 0xffffff or more is undetermined in value (>=  0xffffff).
  268|  73.5k|  const uint32_t count = iter.dom_parser.open_containers[iter.depth].count;
  269|  73.5k|  const uint32_t cntsat = count > 0xFFFFFF ? 0xFFFFFF : count;
  ------------------
  |  Branch (269:27): [True: 0, False: 73.5k]
  ------------------
  270|  73.5k|  tape_writer::write(iter.dom_parser.doc->tape[start_tape_index], next_tape_index(iter) | (uint64_t(cntsat) << 32), start);
  271|  73.5k|  return SUCCESS;
  272|  73.5k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder17visit_array_startERNS2_13json_iteratorE:
  129|  77.4k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_array_start(json_iterator &iter) noexcept {
  130|  77.4k|  start_container(iter);
  131|  77.4k|  return SUCCESS;
  132|  77.4k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder15visit_array_endERNS2_13json_iteratorE:
  137|  63.7k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_array_end(json_iterator &iter) noexcept {
  138|  63.7k|  return end_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY);
  139|  63.7k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage212tape_builder18visit_document_endERNS2_13json_iteratorE:
  140|  6.63k|simdjson_warn_unused simdjson_inline error_code tape_builder::visit_document_end(json_iterator &iter) noexcept {
  141|  6.63k|  constexpr uint32_t start_tape_index = 0;
  142|  6.63k|  tape.append(start_tape_index, internal::tape_type::ROOT);
  143|  6.63k|  tape_writer::write(iter.dom_parser.doc->tape[start_tape_index], next_tape_index(iter), internal::tape_type::ROOT);
  144|  6.63k|  return SUCCESS;
  145|  6.63k|}

simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer4skipEv:
   83|  99.2k|simdjson_inline void tape_writer::skip() noexcept {
   84|  99.2k|  next_tape_loc++;
   85|  99.2k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer6appendEmNS_8internal9tape_typeE:
   95|  5.48M|simdjson_inline void tape_writer::append(uint64_t val, internal::tape_type t) noexcept {
   96|  5.48M|  *next_tape_loc = val | ((uint64_t(char(t))) << 56);
   97|  5.48M|  next_tape_loc++;
   98|  5.48M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer13append_doubleEd:
   79|  2.78M|simdjson_inline void tape_writer::append_double(double value) noexcept {
   80|  2.78M|  append2(0, value, internal::tape_type::DOUBLE);
   81|  2.78M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer7append2IdEEvmT_NS_8internal9tape_typeE:
  101|  2.78M|simdjson_inline void tape_writer::append2(uint64_t val, T val2, internal::tape_type t) noexcept {
  102|  2.78M|  append(val, t);
  103|  2.78M|  static_assert(sizeof(val2) == sizeof(*next_tape_loc), "Type is not 64 bits!");
  104|  2.78M|  memcpy(next_tape_loc, &val2, sizeof(val2));
  105|  2.78M|  next_tape_loc++;
  106|  2.78M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer10append_s64El:
   68|  2.34M|simdjson_inline void tape_writer::append_s64(int64_t value) noexcept {
   69|  2.34M|  append2(0, value, internal::tape_type::INT64);
   70|  2.34M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer7append2IlEEvmT_NS_8internal9tape_typeE:
  101|  2.34M|simdjson_inline void tape_writer::append2(uint64_t val, T val2, internal::tape_type t) noexcept {
  102|  2.34M|  append(val, t);
  103|  2.34M|  static_assert(sizeof(val2) == sizeof(*next_tape_loc), "Type is not 64 bits!");
  104|  2.34M|  memcpy(next_tape_loc, &val2, sizeof(val2));
  105|  2.34M|  next_tape_loc++;
  106|  2.34M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer10append_u64Em:
   72|  1.88k|simdjson_inline void tape_writer::append_u64(uint64_t value) noexcept {
   73|  1.88k|  append(0, internal::tape_type::UINT64);
   74|  1.88k|  *next_tape_loc = value;
   75|  1.88k|  next_tape_loc++;
   76|  1.88k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_16stage211tape_writer5writeERmmNS_8internal9tape_typeE:
  108|  80.1k|simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, internal::tape_type t) noexcept {
  109|  80.1k|  tape_loc = val | ((uint64_t(char(t))) << 56);
  110|  80.1k|}

_ZNK8simdjson7haswell14implementation32create_dom_parser_implementationEmmRNSt3__110unique_ptrINS_8internal25dom_parser_implementationENS2_14default_deleteIS5_EEEE:
   27|  10.8k|) const noexcept {
   28|  10.8k|  dst.reset( new (std::nothrow) dom_parser_implementation() );
   29|  10.8k|  if (!dst) { return MEMALLOC; }
  ------------------
  |  Branch (29:7): [True: 0, False: 10.8k]
  ------------------
   30|  10.8k|  if (auto err = dst->set_capacity(capacity))
  ------------------
  |  Branch (30:12): [True: 0, False: 10.8k]
  ------------------
   31|      0|    return err;
   32|  10.8k|  if (auto err = dst->set_max_depth(max_depth))
  ------------------
  |  Branch (32:12): [True: 0, False: 10.8k]
  ------------------
   33|      0|    return err;
   34|  10.8k|  return SUCCESS;
   35|  10.8k|}
_ZN8simdjson7haswell25dom_parser_implementation6stage1EPKhmNS_11stage1_modeE:
  132|  10.8k|simdjson_warn_unused error_code dom_parser_implementation::stage1(const uint8_t *_buf, size_t _len, stage1_mode streaming) noexcept {
  133|  10.8k|  this->buf = _buf;
  134|  10.8k|  this->len = _len;
  135|  10.8k|  return haswell::stage1::json_structural_indexer::index<128>(_buf, _len, *this, streaming);
  136|  10.8k|}
_ZN8simdjson7haswell25dom_parser_implementation6stage2ERNS_3dom8documentE:
  142|  9.93k|simdjson_warn_unused error_code dom_parser_implementation::stage2(dom::document &_doc) noexcept {
  143|  9.93k|  return stage2::tape_builder::parse_document<false>(*this, _doc);
  144|  9.93k|}
_ZN8simdjson7haswell25dom_parser_implementation5parseEPKhmRNS_3dom8documentE:
  159|  10.8k|simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
  160|  10.8k|  auto error = stage1(_buf, _len, stage1_mode::regular);
  161|  10.8k|  if (error) { return error; }
  ------------------
  |  Branch (161:7): [True: 918, False: 9.93k]
  ------------------
  162|  9.93k|  return stage2(_doc);
  163|  10.8k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_18is_asciiERKNS1_4simd8simd8x64IhEE:
   96|  1.54M|simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input) {
   97|  1.54M|  return input.reduce_or().is_ascii();
   98|  1.54M|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_124must_be_2_3_continuationENS1_4simd5simd8IhEES4_:
  108|  12.1k|simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
  109|  12.1k|  simd8<uint8_t> is_third_byte  = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
  110|  12.1k|  simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
  111|  12.1k|  return is_third_byte | is_fourth_byte;
  112|  12.1k|}
simdjson.cpp:_ZN8simdjson7haswell12_GLOBAL__N_120json_character_block8classifyERKNS1_4simd8simd8x64IhEE:
   43|  1.54M|simdjson_inline json_character_block json_character_block::classify(const simd::simd8x64<uint8_t>& in) {
   44|       |  // These lookups rely on the fact that anything < 127 will match the lower 4 bits, which is why
   45|       |  // we can't use the generic lookup_16.
   46|  1.54M|  const auto whitespace_table = simd8<uint8_t>::repeat_16(' ', 100, 100, 100, 17, 100, 113, 2, 100, '\t', '\n', 112, 100, '\r', 100, 100);
   47|       |
   48|       |  // The 6 operators (:,[]{}) have these values:
   49|       |  //
   50|       |  // , 2C
   51|       |  // : 3A
   52|       |  // [ 5B
   53|       |  // { 7B
   54|       |  // ] 5D
   55|       |  // } 7D
   56|       |  //
   57|       |  // If you use | 0x20 to turn [ and ] into { and }, the lower 4 bits of each character is unique.
   58|       |  // We exploit this, using a simd 4-bit lookup to tell us which character match against, and then
   59|       |  // match it (against | 0x20).
   60|       |  //
   61|       |  // To prevent recognizing other characters, everything else gets compared with 0, which cannot
   62|       |  // match due to the | 0x20.
   63|       |  //
   64|       |  // NOTE: Due to the | 0x20, this ALSO treats <FF> and <SUB> (control characters 0C and 1A) like ,
   65|       |  // and :. This gets caught in stage 2, which checks the actual character to ensure the right
   66|       |  // operators are in the right places.
   67|  1.54M|  const auto op_table = simd8<uint8_t>::repeat_16(
   68|  1.54M|    0, 0, 0, 0,
   69|  1.54M|    0, 0, 0, 0,
   70|  1.54M|    0, 0, ':', '{', // : = 3A, [ = 5B, { = 7B
   71|  1.54M|    ',', '}', 0, 0  // , = 2C, ] = 5D, } = 7D
   72|  1.54M|  );
   73|       |
   74|       |  // We compute whitespace and op separately. If later code only uses one or the
   75|       |  // other, given the fact that all functions are aggressively inlined, we can
   76|       |  // hope that useless computations will be omitted. This is namely case when
   77|       |  // minifying (we only need whitespace).
   78|       |
   79|  1.54M|  const uint64_t whitespace = in.eq({
   80|  1.54M|    _mm256_shuffle_epi8(whitespace_table, in.chunks[0]),
   81|  1.54M|    _mm256_shuffle_epi8(whitespace_table, in.chunks[1])
   82|  1.54M|  });
   83|       |  // Turn [ and ] into { and }
   84|  1.54M|  const simd8x64<uint8_t> curlified{
   85|  1.54M|    in.chunks[0] | 0x20,
   86|  1.54M|    in.chunks[1] | 0x20
   87|  1.54M|  };
   88|  1.54M|  const uint64_t op = curlified.eq({
   89|  1.54M|    _mm256_shuffle_epi8(op_table, in.chunks[0]),
   90|  1.54M|    _mm256_shuffle_epi8(op_table, in.chunks[1])
   91|  1.54M|  });
   92|       |
   93|  1.54M|  return { whitespace, op };
   94|  1.54M|}

_ZNK8simdjson8internal29available_implementation_list21detect_best_supportedEv:
  268|      1|const implementation *available_implementation_list::detect_best_supported() const noexcept {
  269|       |  // They are prelisted in priority order, so we just go down the list
  270|      1|  uint32_t supported_instruction_sets = internal::detect_supported_architectures();
  271|      2|  for (const implementation *impl : internal::get_available_implementation_pointers()) {
  ------------------
  |  Branch (271:35): [True: 2, False: 0]
  ------------------
  272|      2|    uint32_t required_instruction_sets = impl->required_instruction_sets();
  273|      2|    if ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets) { return impl; }
  ------------------
  |  Branch (273:9): [True: 1, False: 1]
  ------------------
  274|      2|  }
  275|      0|  return get_unsupported_singleton(); // this should never happen?
  276|      1|}
_ZNK8simdjson8internal49detect_best_supported_implementation_on_first_use8set_bestEv:
  278|      1|const implementation *detect_best_supported_implementation_on_first_use::set_best() const noexcept {
  279|      1|  SIMDJSON_PUSH_DISABLE_WARNINGS
  280|       |  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
  281|      1|  char *force_implementation_name = getenv("SIMDJSON_FORCE_IMPLEMENTATION");
  282|      1|  SIMDJSON_POP_DISABLE_WARNINGS
  283|       |
  284|      1|  if (force_implementation_name) {
  ------------------
  |  Branch (284:7): [True: 0, False: 1]
  ------------------
  285|      0|    auto force_implementation = get_available_implementations()[force_implementation_name];
  286|      0|    if (force_implementation) {
  ------------------
  |  Branch (286:9): [True: 0, False: 0]
  ------------------
  287|      0|      return get_active_implementation() = force_implementation;
  288|      0|    } else {
  289|       |      // Note: abort() and stderr usage within the library is forbidden.
  290|      0|      return get_active_implementation() = get_unsupported_singleton();
  291|      0|    }
  292|      0|  }
  293|      1|  return get_active_implementation() = get_available_implementations().detect_best_supported();
  294|      1|}
_ZN8simdjson29get_available_implementationsEv:
  298|      1|SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list& get_available_implementations() {
  299|      1|  static const internal::available_implementation_list available_implementations{};
  300|      1|  return available_implementations;
  301|      1|}
_ZN8simdjson25get_active_implementationEv:
  303|  10.8k|SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr<const implementation>& get_active_implementation() {
  304|       |#if SIMDJSON_SINGLE_IMPLEMENTATION
  305|       |  // We immediately select the only implementation we have, skipping the
  306|       |  // detect_best_supported_implementation_on_first_use_singleton.
  307|       |  static internal::atomic_ptr<const implementation> active_implementation{internal::get_single_implementation()};
  308|       |  return active_implementation;
  309|       |#else
  310|  10.8k|  static const internal::detect_best_supported_implementation_on_first_use detect_best_supported_implementation_on_first_use_singleton;
  311|  10.8k|  static internal::atomic_ptr<const implementation> active_implementation{&detect_best_supported_implementation_on_first_use_singleton};
  312|  10.8k|  return active_implementation;
  313|  10.8k|#endif
  314|  10.8k|}
simdjson.cpp:_ZN8simdjson8internalL37get_available_implementation_pointersEv:
  196|      1|static const std::initializer_list<const implementation *>& get_available_implementation_pointers() {
  197|      1|  static const std::initializer_list<const implementation *> available_implementation_pointers {
  198|      1|#if SIMDJSON_IMPLEMENTATION_ICELAKE
  199|      1|    get_icelake_singleton(),
  200|      1|#endif
  201|      1|#if SIMDJSON_IMPLEMENTATION_HASWELL
  202|      1|    get_haswell_singleton(),
  203|      1|#endif
  204|      1|#if SIMDJSON_IMPLEMENTATION_WESTMERE
  205|      1|    get_westmere_singleton(),
  206|      1|#endif
  207|       |#if SIMDJSON_IMPLEMENTATION_ARM64
  208|       |    get_arm64_singleton(),
  209|       |#endif
  210|       |#if SIMDJSON_IMPLEMENTATION_PPC64
  211|       |    get_ppc64_singleton(),
  212|       |#endif
  213|       |#if SIMDJSON_IMPLEMENTATION_LSX
  214|       |    get_lsx_singleton(),
  215|       |#endif
  216|       |#if SIMDJSON_IMPLEMENTATION_LASX
  217|       |    get_lasx_singleton(),
  218|       |#endif
  219|      1|#if SIMDJSON_IMPLEMENTATION_FALLBACK
  220|      1|    get_fallback_singleton(),
  221|      1|#endif
  222|      1|  }; // available_implementation_pointers
  223|      1|  return available_implementation_pointers;
  224|      1|}
simdjson.cpp:_ZN8simdjson8internalL21get_icelake_singletonEv:
   65|      1|static const icelake::implementation* get_icelake_singleton() {
   66|      1|  static const icelake::implementation icelake_singleton{};
   67|      1|  return &icelake_singleton;
   68|      1|}
simdjson.cpp:_ZN8simdjson8internalL21get_haswell_singletonEv:
   53|      1|static const haswell::implementation* get_haswell_singleton() {
   54|      1|  static const haswell::implementation haswell_singleton{};
   55|      1|  return &haswell_singleton;
   56|      1|}
simdjson.cpp:_ZN8simdjson8internalL22get_westmere_singletonEv:
   89|      1|static const simdjson::westmere::implementation* get_westmere_singleton() {
   90|      1|  static const simdjson::westmere::implementation westmere_singleton{};
   91|      1|  return &westmere_singleton;
   92|      1|}
simdjson.cpp:_ZN8simdjson8internalL22get_fallback_singletonEv:
   40|      1|static const fallback::implementation* get_fallback_singleton() {
   41|      1|  static const fallback::implementation fallback_singleton{};
   42|      1|  return &fallback_singleton;
   43|      1|}
_ZN8simdjson8internal49detect_best_supported_implementation_on_first_useC2Ev:
  189|      1|  simdjson_inline detect_best_supported_implementation_on_first_use() noexcept : implementation("best_supported_detector", "Detects the best supported implementation and sets it", 0) {}
_ZNK8simdjson8internal49detect_best_supported_implementation_on_first_use32create_dom_parser_implementationEmmRNSt3__110unique_ptrINS0_25dom_parser_implementationENS2_14default_deleteIS4_EEEE:
  180|      1|  ) const noexcept final {
  181|      1|    return set_best()->create_dom_parser_implementation(capacity, max_length, dst);
  182|      1|  }

simdjson.cpp:_ZN8simdjson8internalL30detect_supported_architecturesEv:
  133|      1|static inline uint32_t detect_supported_architectures() {
  134|      1|  uint32_t eax, ebx, ecx, edx;
  135|      1|  uint32_t host_isa = 0x0;
  136|       |
  137|       |  // EBX for EAX=0x1
  138|      1|  eax = 0x1;
  139|      1|  ecx = 0x0;
  140|      1|  cpuid(&eax, &ebx, &ecx, &edx);
  141|       |
  142|      1|  if (ecx & cpuid_sse42_bit) {
  ------------------
  |  Branch (142:7): [True: 1, False: 0]
  ------------------
  143|      1|    host_isa |= instruction_set::SSE42;
  144|      1|  } else {
  145|      0|    return host_isa; // everything after is redundant
  146|      0|  }
  147|       |
  148|      1|  if (ecx & cpuid_pclmulqdq_bit) {
  ------------------
  |  Branch (148:7): [True: 1, False: 0]
  ------------------
  149|      1|    host_isa |= instruction_set::PCLMULQDQ;
  150|      1|  }
  151|       |
  152|       |
  153|      1|  if ((ecx & cpuid_osxsave) != cpuid_osxsave) {
  ------------------
  |  Branch (153:7): [True: 0, False: 1]
  ------------------
  154|      0|    return host_isa;
  155|      0|  }
  156|       |
  157|       |  // xgetbv for checking if the OS saves registers
  158|      1|  uint64_t xcr0 = xgetbv();
  159|       |
  160|      1|  if ((xcr0 & cpuid_avx256_saved) == 0) {
  ------------------
  |  Branch (160:7): [True: 0, False: 1]
  ------------------
  161|      0|    return host_isa;
  162|      0|  }
  163|       |
  164|       |  // ECX for EAX=0x7
  165|      1|  eax = 0x7;
  166|      1|  ecx = 0x0;
  167|      1|  cpuid(&eax, &ebx, &ecx, &edx);
  168|      1|  if (ebx & cpuid_avx2_bit) {
  ------------------
  |  Branch (168:7): [True: 1, False: 0]
  ------------------
  169|      1|    host_isa |= instruction_set::AVX2;
  170|      1|  }
  171|      1|  if (ebx & cpuid_bmi1_bit) {
  ------------------
  |  Branch (171:7): [True: 1, False: 0]
  ------------------
  172|      1|    host_isa |= instruction_set::BMI1;
  173|      1|  }
  174|       |
  175|      1|  if (ebx & cpuid_bmi2_bit) {
  ------------------
  |  Branch (175:7): [True: 1, False: 0]
  ------------------
  176|      1|    host_isa |= instruction_set::BMI2;
  177|      1|  }
  178|       |
  179|      1|  if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) {
  ------------------
  |  Branch (179:7): [True: 1, False: 0]
  ------------------
  180|      1|     return host_isa;
  181|      1|  }
  182|       |
  183|      0|  if (ebx & cpuid_avx512f_bit) {
  ------------------
  |  Branch (183:7): [True: 0, False: 0]
  ------------------
  184|      0|    host_isa |= instruction_set::AVX512F;
  185|      0|  }
  186|       |
  187|      0|  if (ebx & cpuid_avx512dq_bit) {
  ------------------
  |  Branch (187:7): [True: 0, False: 0]
  ------------------
  188|      0|    host_isa |= instruction_set::AVX512DQ;
  189|      0|  }
  190|       |
  191|      0|  if (ebx & cpuid_avx512ifma_bit) {
  ------------------
  |  Branch (191:7): [True: 0, False: 0]
  ------------------
  192|      0|    host_isa |= instruction_set::AVX512IFMA;
  193|      0|  }
  194|       |
  195|      0|  if (ebx & cpuid_avx512pf_bit) {
  ------------------
  |  Branch (195:7): [True: 0, False: 0]
  ------------------
  196|      0|    host_isa |= instruction_set::AVX512PF;
  197|      0|  }
  198|       |
  199|      0|  if (ebx & cpuid_avx512er_bit) {
  ------------------
  |  Branch (199:7): [True: 0, False: 0]
  ------------------
  200|      0|    host_isa |= instruction_set::AVX512ER;
  201|      0|  }
  202|       |
  203|      0|  if (ebx & cpuid_avx512cd_bit) {
  ------------------
  |  Branch (203:7): [True: 0, False: 0]
  ------------------
  204|      0|    host_isa |= instruction_set::AVX512CD;
  205|      0|  }
  206|       |
  207|      0|  if (ebx & cpuid_avx512bw_bit) {
  ------------------
  |  Branch (207:7): [True: 0, False: 0]
  ------------------
  208|      0|    host_isa |= instruction_set::AVX512BW;
  209|      0|  }
  210|       |
  211|      0|  if (ebx & cpuid_avx512vl_bit) {
  ------------------
  |  Branch (211:7): [True: 0, False: 0]
  ------------------
  212|      0|    host_isa |= instruction_set::AVX512VL;
  213|      0|  }
  214|       |
  215|      0|  if (ecx & cpuid_avx512vbmi2_bit) {
  ------------------
  |  Branch (215:7): [True: 0, False: 0]
  ------------------
  216|      0|    host_isa |= instruction_set::AVX512VBMI2;
  217|      0|  }
  218|       |
  219|      0|  return host_isa;
  220|      1|}
simdjson.cpp:_ZN8simdjson8internalL5cpuidEPjS1_S1_S1_:
  101|      2|                         uint32_t *edx) {
  102|       |#if defined(_MSC_VER)
  103|       |  int cpu_info[4];
  104|       |  __cpuidex(cpu_info, *eax, *ecx);
  105|       |  *eax = cpu_info[0];
  106|       |  *ebx = cpu_info[1];
  107|       |  *ecx = cpu_info[2];
  108|       |  *edx = cpu_info[3];
  109|       |#elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
  110|       |  uint32_t level = *eax;
  111|       |  __get_cpuid(level, eax, ebx, ecx, edx);
  112|       |#else
  113|      2|  uint32_t a = *eax, b, c = *ecx, d;
  114|      2|  asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d));
  115|      2|  *eax = a;
  116|      2|  *ebx = b;
  117|      2|  *ecx = c;
  118|      2|  *edx = d;
  119|      2|#endif
  120|      2|}
simdjson.cpp:_ZN8simdjson8internalL6xgetbvEv:
  123|      1|static inline uint64_t xgetbv() {
  124|       |#if defined(_MSC_VER)
  125|       |  return _xgetbv(0);
  126|       |#else
  127|      1|  uint32_t xcr0_lo, xcr0_hi;
  128|      1|  asm volatile("xgetbv\n\t" : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0));
  129|      1|  return xcr0_lo | (uint64_t(xcr0_hi) << 32);
  130|      1|#endif
  131|      1|}

_ZN8simdjson8internal8to_charsEPcPKcd:
  921|  2.77M|char *to_chars(char *first, const char *last, double value) {
  922|  2.77M|  static_cast<void>(last); // maybe unused - fix warning
  923|  2.77M|  bool negative = std::signbit(value);
  924|  2.77M|  if (negative) {
  ------------------
  |  Branch (924:7): [True: 34.5k, False: 2.74M]
  ------------------
  925|  34.5k|    value = -value;
  926|  34.5k|    *first++ = '-';
  927|  34.5k|  }
  928|       |
  929|  2.77M|  if (value == 0) // +-0
  ------------------
  |  Branch (929:7): [True: 51.9k, False: 2.72M]
  ------------------
  930|  51.9k|  {
  931|  51.9k|    *first++ = '0';
  932|       |    // Make it look like a floating-point number (#362, #378)
  933|  51.9k|    *first++ = '.';
  934|  51.9k|    *first++ = '0';
  935|  51.9k|    return first;
  936|  51.9k|  }
  937|       |  // Compute v = buffer * 10^decimal_exponent.
  938|       |  // The decimal digits are stored in the buffer, which needs to be interpreted
  939|       |  // as an unsigned decimal integer.
  940|       |  // len is the length of the buffer, i.e. the number of decimal digits.
  941|  2.72M|  int len = 0;
  942|  2.72M|  int decimal_exponent = 0;
  943|  2.72M|  dtoa_impl::grisu2(first, len, decimal_exponent, value);
  944|       |  // Format the buffer like printf("%.*g", prec, value)
  945|  2.72M|  constexpr int kMinExp = -4;
  946|  2.72M|  constexpr int kMaxExp = std::numeric_limits<double>::digits10;
  947|       |
  948|  2.72M|  return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp,
  949|  2.72M|                                  kMaxExp);
  950|  2.77M|}
_ZN8simdjson8internal9dtoa_impl13format_bufferEPciiii:
  853|  2.72M|                           int min_exp, int max_exp) {
  854|       |
  855|  2.72M|  const int k = len;
  856|  2.72M|  const int n = len + decimal_exponent;
  857|       |
  858|       |  // v = buf * 10^(n-k)
  859|       |  // k is the length of the buffer (number of decimal digits)
  860|       |  // n is the position of the decimal point relative to the start of the buffer.
  861|       |
  862|  2.72M|  if (k <= n && n <= max_exp) {
  ------------------
  |  Branch (862:7): [True: 2.69M, False: 31.3k]
  |  Branch (862:17): [True: 32.9k, False: 2.65M]
  ------------------
  863|       |    // digits[000]
  864|       |    // len <= max_exp + 2
  865|       |
  866|  32.9k|    std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
  867|       |    // Make it look like a floating-point number (#362, #378)
  868|  32.9k|    buf[n + 0] = '.';
  869|  32.9k|    buf[n + 1] = '0';
  870|  32.9k|    return buf + (static_cast<size_t>(n)) + 2;
  871|  32.9k|  }
  872|       |
  873|  2.69M|  if (0 < n && n <= max_exp) {
  ------------------
  |  Branch (873:7): [True: 2.66M, False: 22.3k]
  |  Branch (873:16): [True: 8.99k, False: 2.65M]
  ------------------
  874|       |    // dig.its
  875|       |    // len <= max_digits10 + 1
  876|  8.99k|    std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n,
  877|  8.99k|                 static_cast<size_t>(k) - static_cast<size_t>(n));
  878|  8.99k|    buf[n] = '.';
  879|  8.99k|    return buf + (static_cast<size_t>(k) + 1U);
  880|  8.99k|  }
  881|       |
  882|  2.68M|  if (min_exp < n && n <= 0) {
  ------------------
  |  Branch (882:7): [True: 2.66M, False: 12.8k]
  |  Branch (882:22): [True: 9.46k, False: 2.65M]
  ------------------
  883|       |    // 0.[000]digits
  884|       |    // len <= 2 + (-min_exp - 1) + max_digits10
  885|       |
  886|  9.46k|    std::memmove(buf + (2 + static_cast<size_t>(-n)), buf,
  887|  9.46k|                 static_cast<size_t>(k));
  888|  9.46k|    buf[0] = '0';
  889|  9.46k|    buf[1] = '.';
  890|  9.46k|    std::memset(buf + 2, '0', static_cast<size_t>(-n));
  891|  9.46k|    return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
  892|  9.46k|  }
  893|       |
  894|  2.67M|  if (k == 1) {
  ------------------
  |  Branch (894:7): [True: 28.0k, False: 2.64M]
  ------------------
  895|       |    // dE+123
  896|       |    // len <= 1 + 5
  897|       |
  898|  28.0k|    buf += 1;
  899|  2.64M|  } else {
  900|       |    // d.igitsE+123
  901|       |    // len <= max_digits10 + 1 + 5
  902|       |
  903|  2.64M|    std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
  904|  2.64M|    buf[1] = '.';
  905|  2.64M|    buf += 1 + static_cast<size_t>(k);
  906|  2.64M|  }
  907|       |
  908|  2.67M|  *buf++ = 'e';
  909|  2.67M|  return append_exponent(buf, n - 1);
  910|  2.68M|}
_ZN8simdjson8internal9dtoa_impl15append_exponentEPci:
  815|  2.67M|inline char *append_exponent(char *buf, int e) {
  816|       |
  817|  2.67M|  if (e < 0) {
  ------------------
  |  Branch (817:7): [True: 12.8k, False: 2.65M]
  ------------------
  818|  12.8k|    e = -e;
  819|  12.8k|    *buf++ = '-';
  820|  2.65M|  } else {
  821|  2.65M|    *buf++ = '+';
  822|  2.65M|  }
  823|       |
  824|  2.67M|  auto k = static_cast<std::uint32_t>(e);
  825|  2.67M|  if (k < 10) {
  ------------------
  |  Branch (825:7): [True: 1.65k, False: 2.67M]
  ------------------
  826|       |    // Always print at least two digits in the exponent.
  827|       |    // This is for compatibility with printf("%g").
  828|  1.65k|    *buf++ = '0';
  829|  1.65k|    *buf++ = static_cast<char>('0' + k);
  830|  2.67M|  } else if (k < 100) {
  ------------------
  |  Branch (830:14): [True: 2.65M, False: 13.9k]
  ------------------
  831|  2.65M|    *buf++ = static_cast<char>('0' + k / 10);
  832|  2.65M|    k %= 10;
  833|  2.65M|    *buf++ = static_cast<char>('0' + k);
  834|  2.65M|  } else {
  835|  13.9k|    *buf++ = static_cast<char>('0' + k / 100);
  836|  13.9k|    k %= 100;
  837|  13.9k|    *buf++ = static_cast<char>('0' + k / 10);
  838|  13.9k|    k %= 10;
  839|  13.9k|    *buf++ = static_cast<char>('0' + k);
  840|  13.9k|  }
  841|       |
  842|  2.67M|  return buf;
  843|  2.67M|}
_ZN8simdjson8internal9dtoa_impl6grisu2IdEEvPcRiS4_T_:
  778|  2.72M|void grisu2(char *buf, int &len, int &decimal_exponent, FloatType value) {
  779|  2.72M|  static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
  780|  2.72M|                "internal error: not enough precision");
  781|       |
  782|       |  // If the neighbors (and boundaries) of 'value' are always computed for
  783|       |  // double-precision numbers, all float's can be recovered using strtod (and
  784|       |  // strtof). However, the resulting decimal representations are not exactly
  785|       |  // "short".
  786|       |  //
  787|       |  // The documentation for 'std::to_chars'
  788|       |  // (https://en.cppreference.com/w/cpp/utility/to_chars) says "value is
  789|       |  // converted to a string as if by std::sprintf in the default ("C") locale"
  790|       |  // and since sprintf promotes float's to double's, I think this is exactly
  791|       |  // what 'std::to_chars' does. On the other hand, the documentation for
  792|       |  // 'std::to_chars' requires that "parsing the representation using the
  793|       |  // corresponding std::from_chars function recovers value exactly". That
  794|       |  // indicates that single precision floating-point numbers should be recovered
  795|       |  // using 'std::strtof'.
  796|       |  //
  797|       |  // NB: If the neighbors are computed for single-precision numbers, there is a
  798|       |  // single float
  799|       |  //     (7.0385307e-26f) which can't be recovered using strtod. The resulting
  800|       |  //     double precision value is off by 1 ulp.
  801|       |#if 0
  802|       |    const boundaries w = compute_boundaries(static_cast<double>(value));
  803|       |#else
  804|  2.72M|  const boundaries w = compute_boundaries(value);
  805|  2.72M|#endif
  806|       |
  807|  2.72M|  grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
  808|  2.72M|}
_ZN8simdjson8internal9dtoa_impl18compute_boundariesIdEENS1_10boundariesET_:
  160|  2.72M|template <typename FloatType> boundaries compute_boundaries(FloatType value) {
  161|       |
  162|       |  // Convert the IEEE representation into a diyfp.
  163|       |  //
  164|       |  // If v is denormal:
  165|       |  //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
  166|       |  // If v is normalized:
  167|       |  //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
  168|       |
  169|  2.72M|  static_assert(std::numeric_limits<FloatType>::is_iec559,
  170|  2.72M|                "internal error: dtoa_short requires an IEEE-754 "
  171|  2.72M|                "floating-point implementation");
  172|       |
  173|  2.72M|  constexpr int kPrecision =
  174|  2.72M|      std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
  175|  2.72M|  constexpr int kBias =
  176|  2.72M|      std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
  177|  2.72M|  constexpr int kMinExp = 1 - kBias;
  178|  2.72M|  constexpr std::uint64_t kHiddenBit = std::uint64_t{1}
  179|  2.72M|                                       << (kPrecision - 1); // = 2^(p-1)
  180|       |
  181|  2.72M|  using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t,
  182|  2.72M|                                              std::uint64_t>::type;
  183|       |
  184|  2.72M|  const std::uint64_t bits = reinterpret_bits<bits_type>(value);
  185|  2.72M|  const std::uint64_t E = bits >> (kPrecision - 1);
  186|  2.72M|  const std::uint64_t F = bits & (kHiddenBit - 1);
  187|       |
  188|  2.72M|  const bool is_denormal = E == 0;
  189|  2.72M|  const diyfp v = is_denormal
  ------------------
  |  Branch (189:19): [True: 8.90k, False: 2.71M]
  ------------------
  190|  2.72M|                      ? diyfp(F, kMinExp)
  191|  2.72M|                      : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
  192|       |
  193|       |  // Compute the boundaries m- and m+ of the floating-point value
  194|       |  // v = f * 2^e.
  195|       |  //
  196|       |  // Determine v- and v+, the floating-point predecessor and successor if v,
  197|       |  // respectively.
  198|       |  //
  199|       |  //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
  200|       |  //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
  201|       |  //
  202|       |  //      v+ = v + 2^e
  203|       |  //
  204|       |  // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
  205|       |  // between m- and m+ round to v, regardless of how the input rounding
  206|       |  // algorithm breaks ties.
  207|       |  //
  208|       |  //      ---+-------------+-------------+-------------+-------------+---  (A)
  209|       |  //         v-            m-            v             m+            v+
  210|       |  //
  211|       |  //      -----------------+------+------+-------------+-------------+---  (B)
  212|       |  //                       v-     m-     v             m+            v+
  213|       |
  214|  2.72M|  const bool lower_boundary_is_closer = F == 0 && E > 1;
  ------------------
  |  Branch (214:41): [True: 8.11k, False: 2.71M]
  |  Branch (214:51): [True: 8.10k, False: 3]
  ------------------
  215|  2.72M|  const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
  216|  2.72M|  const diyfp m_minus = lower_boundary_is_closer
  ------------------
  |  Branch (216:25): [True: 8.10k, False: 2.71M]
  ------------------
  217|  2.72M|                            ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
  218|  2.72M|                            : diyfp(2 * v.f - 1, v.e - 1); // (A)
  219|       |
  220|       |  // Determine the normalized w+ = m+.
  221|  2.72M|  const diyfp w_plus = diyfp::normalize(m_plus);
  222|       |
  223|       |  // Determine w- = m- such that e_(w-) = e_(w+).
  224|  2.72M|  const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
  225|       |
  226|  2.72M|  return {diyfp::normalize(v), w_minus, w_plus};
  227|  2.72M|}
_ZN8simdjson8internal9dtoa_impl16reinterpret_bitsImdEET_T0_:
   32|  2.72M|Target reinterpret_bits(const Source source) {
   33|  2.72M|  static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
   34|       |
   35|  2.72M|  Target target;
   36|  2.72M|  std::memcpy(&target, &source, sizeof(Source));
   37|  2.72M|  return target;
   38|  2.72M|}
_ZN8simdjson8internal9dtoa_impl5diyfpC2Emi:
   47|  35.4M|  constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
_ZN8simdjson8internal9dtoa_impl5diyfp9normalizeES2_:
  127|  5.44M|  static diyfp normalize(diyfp x) noexcept {
  128|       |
  129|  63.4M|    while ((x.f >> 63u) == 0) {
  ------------------
  |  Branch (129:12): [True: 58.0M, False: 5.44M]
  ------------------
  130|  58.0M|      x.f <<= 1u;
  131|  58.0M|      x.e--;
  132|  58.0M|    }
  133|       |
  134|  5.44M|    return x;
  135|  5.44M|  }
_ZN8simdjson8internal9dtoa_impl5diyfp12normalize_toERKS2_i:
  142|  2.72M|                            const int target_exponent) noexcept {
  143|  2.72M|    const int delta = x.e - target_exponent;
  144|       |
  145|  2.72M|    return {x.f << delta, target_exponent};
  146|  2.72M|  }
_ZN8simdjson8internal9dtoa_impl6grisu2EPcRiS3_NS1_5diyfpES4_S4_:
  722|  2.72M|                   diyfp v, diyfp m_plus) {
  723|       |
  724|       |  //  --------(-----------------------+-----------------------)--------    (A)
  725|       |  //          m-                      v                       m+
  726|       |  //
  727|       |  //  --------------------(-----------+-----------------------)--------    (B)
  728|       |  //                      m-          v                       m+
  729|       |  //
  730|       |  // First scale v (and m- and m+) such that the exponent is in the range
  731|       |  // [alpha, gamma].
  732|       |
  733|  2.72M|  const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
  734|       |
  735|  2.72M|  const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
  736|       |
  737|       |  // The exponent of the products is = v.e + c_minus_k.e + q and is in the range
  738|       |  // [alpha,gamma]
  739|  2.72M|  const diyfp w = diyfp::mul(v, c_minus_k);
  740|  2.72M|  const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
  741|  2.72M|  const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
  742|       |
  743|       |  //  ----(---+---)---------------(---+---)---------------(---+---)----
  744|       |  //          w-                      w                       w+
  745|       |  //          = c*m-                  = c*v                   = c*m+
  746|       |  //
  747|       |  // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
  748|       |  // w+ are now off by a small amount.
  749|       |  // In fact:
  750|       |  //
  751|       |  //      w - v * 10^k < 1 ulp
  752|       |  //
  753|       |  // To account for this inaccuracy, add resp. subtract 1 ulp.
  754|       |  //
  755|       |  //  --------+---[---------------(---+---)---------------]---+--------
  756|       |  //          w-  M-                  w                   M+  w+
  757|       |  //
  758|       |  // Now any number in [M-, M+] (bounds included) will round to w when input,
  759|       |  // regardless of how the input rounding algorithm breaks ties.
  760|       |  //
  761|       |  // And digit_gen generates the shortest possible such number in [M-, M+].
  762|       |  // Note that this does not mean that Grisu2 always generates the shortest
  763|       |  // possible number in the interval (m-, m+).
  764|  2.72M|  const diyfp M_minus(w_minus.f + 1, w_minus.e);
  765|  2.72M|  const diyfp M_plus(w_plus.f - 1, w_plus.e);
  766|       |
  767|  2.72M|  decimal_exponent = -cached.k; // = -(-k) = k
  768|       |
  769|  2.72M|  grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
  770|  2.72M|}
_ZN8simdjson8internal9dtoa_impl36get_cached_power_for_binary_exponentEi:
  300|  2.72M|inline cached_power get_cached_power_for_binary_exponent(int e) {
  301|       |  // Now
  302|       |  //
  303|       |  //      alpha <= e_c + e + q <= gamma                                    (1)
  304|       |  //      ==> f_c * 2^alpha <= c * 2^e * 2^q
  305|       |  //
  306|       |  // and since the c's are normalized, 2^(q-1) <= f_c,
  307|       |  //
  308|       |  //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
  309|       |  //      ==> 2^(alpha - e - 1) <= c
  310|       |  //
  311|       |  // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
  312|       |  //
  313|       |  //      k = ceil( log_10( 2^(alpha - e - 1) ) )
  314|       |  //        = ceil( (alpha - e - 1) * log_10(2) )
  315|       |  //
  316|       |  // From the paper:
  317|       |  // "In theory the result of the procedure could be wrong since c is rounded,
  318|       |  //  and the computation itself is approximated [...]. In practice, however,
  319|       |  //  this simple function is sufficient."
  320|       |  //
  321|       |  // For IEEE double precision floating-point numbers converted into
  322|       |  // normalized diyfp's w = f * 2^e, with q = 64,
  323|       |  //
  324|       |  //      e >= -1022      (min IEEE exponent)
  325|       |  //           -52        (p - 1)
  326|       |  //           -52        (p - 1, possibly normalize denormal IEEE numbers)
  327|       |  //           -11        (normalize the diyfp)
  328|       |  //         = -1137
  329|       |  //
  330|       |  // and
  331|       |  //
  332|       |  //      e <= +1023      (max IEEE exponent)
  333|       |  //           -52        (p - 1)
  334|       |  //           -11        (normalize the diyfp)
  335|       |  //         = 960
  336|       |  //
  337|       |  // This binary exponent range [-1137,960] results in a decimal exponent
  338|       |  // range [-307,324]. One does not need to store a cached power for each
  339|       |  // k in this range. For each such k it suffices to find a cached power
  340|       |  // such that the exponent of the product lies in [alpha,gamma].
  341|       |  // This implies that the difference of the decimal exponents of adjacent
  342|       |  // table entries must be less than or equal to
  343|       |  //
  344|       |  //      floor( (gamma - alpha) * log_10(2) ) = 8.
  345|       |  //
  346|       |  // (A smaller distance gamma-alpha would require a larger table.)
  347|       |
  348|       |  // NB:
  349|       |  // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
  350|       |
  351|  2.72M|  constexpr int kCachedPowersMinDecExp = -300;
  352|  2.72M|  constexpr int kCachedPowersDecStep = 8;
  353|       |
  354|  2.72M|  static constexpr std::array<cached_power, 79> kCachedPowers = {{
  355|  2.72M|      {0xAB70FE17C79AC6CA, -1060, -300}, {0xFF77B1FCBEBCDC4F, -1034, -292},
  356|  2.72M|      {0xBE5691EF416BD60C, -1007, -284}, {0x8DD01FAD907FFC3C, -980, -276},
  357|  2.72M|      {0xD3515C2831559A83, -954, -268},  {0x9D71AC8FADA6C9B5, -927, -260},
  358|  2.72M|      {0xEA9C227723EE8BCB, -901, -252},  {0xAECC49914078536D, -874, -244},
  359|  2.72M|      {0x823C12795DB6CE57, -847, -236},  {0xC21094364DFB5637, -821, -228},
  360|  2.72M|      {0x9096EA6F3848984F, -794, -220},  {0xD77485CB25823AC7, -768, -212},
  361|  2.72M|      {0xA086CFCD97BF97F4, -741, -204},  {0xEF340A98172AACE5, -715, -196},
  362|  2.72M|      {0xB23867FB2A35B28E, -688, -188},  {0x84C8D4DFD2C63F3B, -661, -180},
  363|  2.72M|      {0xC5DD44271AD3CDBA, -635, -172},  {0x936B9FCEBB25C996, -608, -164},
  364|  2.72M|      {0xDBAC6C247D62A584, -582, -156},  {0xA3AB66580D5FDAF6, -555, -148},
  365|  2.72M|      {0xF3E2F893DEC3F126, -529, -140},  {0xB5B5ADA8AAFF80B8, -502, -132},
  366|  2.72M|      {0x87625F056C7C4A8B, -475, -124},  {0xC9BCFF6034C13053, -449, -116},
  367|  2.72M|      {0x964E858C91BA2655, -422, -108},  {0xDFF9772470297EBD, -396, -100},
  368|  2.72M|      {0xA6DFBD9FB8E5B88F, -369, -92},   {0xF8A95FCF88747D94, -343, -84},
  369|  2.72M|      {0xB94470938FA89BCF, -316, -76},   {0x8A08F0F8BF0F156B, -289, -68},
  370|  2.72M|      {0xCDB02555653131B6, -263, -60},   {0x993FE2C6D07B7FAC, -236, -52},
  371|  2.72M|      {0xE45C10C42A2B3B06, -210, -44},   {0xAA242499697392D3, -183, -36},
  372|  2.72M|      {0xFD87B5F28300CA0E, -157, -28},   {0xBCE5086492111AEB, -130, -20},
  373|  2.72M|      {0x8CBCCC096F5088CC, -103, -12},   {0xD1B71758E219652C, -77, -4},
  374|  2.72M|      {0x9C40000000000000, -50, 4},      {0xE8D4A51000000000, -24, 12},
  375|  2.72M|      {0xAD78EBC5AC620000, 3, 20},       {0x813F3978F8940984, 30, 28},
  376|  2.72M|      {0xC097CE7BC90715B3, 56, 36},      {0x8F7E32CE7BEA5C70, 83, 44},
  377|  2.72M|      {0xD5D238A4ABE98068, 109, 52},     {0x9F4F2726179A2245, 136, 60},
  378|  2.72M|      {0xED63A231D4C4FB27, 162, 68},     {0xB0DE65388CC8ADA8, 189, 76},
  379|  2.72M|      {0x83C7088E1AAB65DB, 216, 84},     {0xC45D1DF942711D9A, 242, 92},
  380|  2.72M|      {0x924D692CA61BE758, 269, 100},    {0xDA01EE641A708DEA, 295, 108},
  381|  2.72M|      {0xA26DA3999AEF774A, 322, 116},    {0xF209787BB47D6B85, 348, 124},
  382|  2.72M|      {0xB454E4A179DD1877, 375, 132},    {0x865B86925B9BC5C2, 402, 140},
  383|  2.72M|      {0xC83553C5C8965D3D, 428, 148},    {0x952AB45CFA97A0B3, 455, 156},
  384|  2.72M|      {0xDE469FBD99A05FE3, 481, 164},    {0xA59BC234DB398C25, 508, 172},
  385|  2.72M|      {0xF6C69A72A3989F5C, 534, 180},    {0xB7DCBF5354E9BECE, 561, 188},
  386|  2.72M|      {0x88FCF317F22241E2, 588, 196},    {0xCC20CE9BD35C78A5, 614, 204},
  387|  2.72M|      {0x98165AF37B2153DF, 641, 212},    {0xE2A0B5DC971F303A, 667, 220},
  388|  2.72M|      {0xA8D9D1535CE3B396, 694, 228},    {0xFB9B7CD9A4A7443C, 720, 236},
  389|  2.72M|      {0xBB764C4CA7A44410, 747, 244},    {0x8BAB8EEFB6409C1A, 774, 252},
  390|  2.72M|      {0xD01FEF10A657842C, 800, 260},    {0x9B10A4E5E9913129, 827, 268},
  391|  2.72M|      {0xE7109BFBA19C0C9D, 853, 276},    {0xAC2820D9623BF429, 880, 284},
  392|  2.72M|      {0x80444B5E7AA7CF85, 907, 292},    {0xBF21E44003ACDD2D, 933, 300},
  393|  2.72M|      {0x8E679C2F5E44FF8F, 960, 308},    {0xD433179D9C8CB841, 986, 316},
  394|  2.72M|      {0x9E19DB92B4E31BA9, 1013, 324},
  395|  2.72M|  }};
  396|       |
  397|       |  // This computation gives exactly the same results for k as
  398|       |  //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
  399|       |  // for |e| <= 1500, but doesn't require floating-point operations.
  400|       |  // NB: log_10(2) ~= 78913 / 2^18
  401|  2.72M|  const int f = kAlpha - e - 1;
  402|  2.72M|  const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
  403|       |
  404|  2.72M|  const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) /
  405|  2.72M|                    kCachedPowersDecStep;
  406|       |
  407|  2.72M|  const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
  408|       |
  409|  2.72M|  return cached;
  410|  2.72M|}
_ZN8simdjson8internal9dtoa_impl5diyfp3mulERKS2_S4_:
   62|  8.17M|  static diyfp mul(const diyfp &x, const diyfp &y) noexcept {
   63|  8.17M|    static_assert(kPrecision == 64, "internal error");
   64|       |
   65|       |    // Computes:
   66|       |    //  f = round((x.f * y.f) / 2^q)
   67|       |    //  e = x.e + y.e + q
   68|       |
   69|       |    // Emulate the 64-bit * 64-bit multiplication:
   70|       |    //
   71|       |    // p = u * v
   72|       |    //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
   73|       |    //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo )) +
   74|       |    //   2^64 (u_hi v_hi         ) = (p0                ) + 2^32 ((p1 ) + (p2 ))
   75|       |    //   + 2^64 (p3                ) = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo +
   76|       |    //   2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                ) =
   77|       |    //   (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi +
   78|       |    //   p2_hi + p3) = (p0_lo             ) + 2^32 (Q ) + 2^64 (H ) = (p0_lo ) +
   79|       |    //   2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H )
   80|       |    //
   81|       |    // (Since Q might be larger than 2^32 - 1)
   82|       |    //
   83|       |    //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
   84|       |    //
   85|       |    // (Q_hi + H does not overflow a 64-bit int)
   86|       |    //
   87|       |    //   = p_lo + 2^64 p_hi
   88|       |
   89|  8.17M|    const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
   90|  8.17M|    const std::uint64_t u_hi = x.f >> 32u;
   91|  8.17M|    const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
   92|  8.17M|    const std::uint64_t v_hi = y.f >> 32u;
   93|       |
   94|  8.17M|    const std::uint64_t p0 = u_lo * v_lo;
   95|  8.17M|    const std::uint64_t p1 = u_lo * v_hi;
   96|  8.17M|    const std::uint64_t p2 = u_hi * v_lo;
   97|  8.17M|    const std::uint64_t p3 = u_hi * v_hi;
   98|       |
   99|  8.17M|    const std::uint64_t p0_hi = p0 >> 32u;
  100|  8.17M|    const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
  101|  8.17M|    const std::uint64_t p1_hi = p1 >> 32u;
  102|  8.17M|    const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
  103|  8.17M|    const std::uint64_t p2_hi = p2 >> 32u;
  104|       |
  105|  8.17M|    std::uint64_t Q = p0_hi + p1_lo + p2_lo;
  106|       |
  107|       |    // The full product might now be computed as
  108|       |    //
  109|       |    // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
  110|       |    // p_lo = p0_lo + (Q << 32)
  111|       |    //
  112|       |    // But in this particular case here, the full p_lo is not required.
  113|       |    // Effectively we only need to add the highest bit in p_lo to p_hi (and
  114|       |    // Q_hi + 1 does not overflow).
  115|       |
  116|  8.17M|    Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
  117|       |
  118|  8.17M|    const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
  119|       |
  120|  8.17M|    return {h, x.e + y.e + 64};
  121|  8.17M|  }
_ZN8simdjson8internal9dtoa_impl16grisu2_digit_genEPcRiS3_NS1_5diyfpES4_S4_:
  488|  2.72M|                             diyfp M_minus, diyfp w, diyfp M_plus) {
  489|  2.72M|  static_assert(kAlpha >= -60, "internal error");
  490|  2.72M|  static_assert(kGamma <= -32, "internal error");
  491|       |
  492|       |  // Generates the digits (and the exponent) of a decimal floating-point
  493|       |  // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
  494|       |  // w, M- and M+ share the same exponent e, which satisfies alpha <= e <=
  495|       |  // gamma.
  496|       |  //
  497|       |  //               <--------------------------- delta ---->
  498|       |  //                                  <---- dist --------->
  499|       |  // --------------[------------------+-------------------]--------------
  500|       |  //               M-                 w                   M+
  501|       |  //
  502|       |  // Grisu2 generates the digits of M+ from left to right and stops as soon as
  503|       |  // V is in [M-,M+].
  504|       |
  505|  2.72M|  std::uint64_t delta =
  506|  2.72M|      diyfp::sub(M_plus, M_minus)
  507|  2.72M|          .f; // (significand of (M+ - M-), implicit exponent is e)
  508|  2.72M|  std::uint64_t dist =
  509|  2.72M|      diyfp::sub(M_plus, w)
  510|  2.72M|          .f; // (significand of (M+ - w ), implicit exponent is e)
  511|       |
  512|       |  // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
  513|       |  //
  514|       |  //      M+ = f * 2^e
  515|       |  //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
  516|       |  //         = ((p1        ) * 2^-e + (p2        )) * 2^e
  517|       |  //         = p1 + p2 * 2^e
  518|       |
  519|  2.72M|  const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
  520|       |
  521|  2.72M|  auto p1 = static_cast<std::uint32_t>(
  522|  2.72M|      M_plus.f >>
  523|  2.72M|      -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
  524|  2.72M|  std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
  525|       |
  526|       |  // 1)
  527|       |  //
  528|       |  // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
  529|       |
  530|  2.72M|  std::uint32_t pow10;
  531|  2.72M|  const int k = find_largest_pow10(p1, pow10);
  532|       |
  533|       |  //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
  534|       |  //
  535|       |  //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
  536|       |  //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
  537|       |  //
  538|       |  //      M+ = p1                                             + p2 * 2^e
  539|       |  //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
  540|       |  //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
  541|       |  //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
  542|       |  //
  543|       |  // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
  544|       |  //
  545|       |  //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
  546|       |  //
  547|       |  // but stop as soon as
  548|       |  //
  549|       |  //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
  550|       |
  551|  2.72M|  int n = k;
  552|  13.2M|  while (n > 0) {
  ------------------
  |  Branch (552:10): [True: 10.5M, False: 2.62M]
  ------------------
  553|       |    // Invariants:
  554|       |    //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
  555|       |    //      pow10 = 10^(n-1) <= p1 < 10^n
  556|       |    //
  557|  10.5M|    const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
  558|  10.5M|    const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
  559|       |    //
  560|       |    //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
  561|       |    //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
  562|       |    //
  563|  10.5M|    buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  564|       |    //
  565|       |    //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
  566|       |    //
  567|  10.5M|    p1 = r;
  568|  10.5M|    n--;
  569|       |    //
  570|       |    //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
  571|       |    //      pow10 = 10^n
  572|       |    //
  573|       |
  574|       |    // Now check if enough digits have been generated.
  575|       |    // Compute
  576|       |    //
  577|       |    //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
  578|       |    //
  579|       |    // Note:
  580|       |    // Since rest and delta share the same exponent e, it suffices to
  581|       |    // compare the significands.
  582|  10.5M|    const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
  583|  10.5M|    if (rest <= delta) {
  ------------------
  |  Branch (583:9): [True: 97.4k, False: 10.4M]
  ------------------
  584|       |      // V = buffer * 10^n, with M- <= V <= M+.
  585|       |
  586|  97.4k|      decimal_exponent += n;
  587|       |
  588|       |      // We may now just stop. But instead look if the buffer could be
  589|       |      // decremented to bring V closer to w.
  590|       |      //
  591|       |      // pow10 = 10^n is now 1 ulp in the decimal representation V.
  592|       |      // The rounding procedure works with diyfp's with an implicit
  593|       |      // exponent of e.
  594|       |      //
  595|       |      //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
  596|       |      //
  597|  97.4k|      const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
  598|  97.4k|      grisu2_round(buffer, length, dist, delta, rest, ten_n);
  599|       |
  600|  97.4k|      return;
  601|  97.4k|    }
  602|       |
  603|  10.4M|    pow10 /= 10;
  604|       |    //
  605|       |    //      pow10 = 10^(n-1) <= p1 < 10^n
  606|       |    // Invariants restored.
  607|  10.4M|  }
  608|       |
  609|       |  // 2)
  610|       |  //
  611|       |  // The digits of the integral part have been generated:
  612|       |  //
  613|       |  //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
  614|       |  //         = buffer            + p2 * 2^e
  615|       |  //
  616|       |  // Now generate the digits of the fractional part p2 * 2^e.
  617|       |  //
  618|       |  // Note:
  619|       |  // No decimal point is generated: the exponent is adjusted instead.
  620|       |  //
  621|       |  // p2 actually represents the fraction
  622|       |  //
  623|       |  //      p2 * 2^e
  624|       |  //          = p2 / 2^-e
  625|       |  //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
  626|       |  //
  627|       |  // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
  628|       |  //
  629|       |  //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
  630|       |  //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
  631|       |  //
  632|       |  // using
  633|       |  //
  634|       |  //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
  635|       |  //                = (                   d) * 2^-e + (                   r)
  636|       |  //
  637|       |  // or
  638|       |  //      10^m * p2 * 2^e = d + r * 2^e
  639|       |  //
  640|       |  // i.e.
  641|       |  //
  642|       |  //      M+ = buffer + p2 * 2^e
  643|       |  //         = buffer + 10^-m * (d + r * 2^e)
  644|       |  //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
  645|       |  //
  646|       |  // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
  647|       |
  648|  2.62M|  int m = 0;
  649|  34.1M|  for (;;) {
  650|       |    // Invariant:
  651|       |    //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...)
  652|       |    //      * 2^e
  653|       |    //         = buffer * 10^-m + 10^-m * (p2                                 )
  654|       |    //         * 2^e = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e =
  655|       |    //         buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e +
  656|       |    //         (10*p2 mod 2^-e)) * 2^e
  657|       |    //
  658|  34.1M|    p2 *= 10;
  659|  34.1M|    const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
  660|  34.1M|    const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
  661|       |    //
  662|       |    //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
  663|       |    //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
  664|       |    //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
  665|       |    //
  666|  34.1M|    buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  667|       |    //
  668|       |    //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
  669|       |    //
  670|  34.1M|    p2 = r;
  671|  34.1M|    m++;
  672|       |    //
  673|       |    //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
  674|       |    // Invariant restored.
  675|       |
  676|       |    // Check if enough digits have been generated.
  677|       |    //
  678|       |    //      10^-m * p2 * 2^e <= delta * 2^e
  679|       |    //              p2 * 2^e <= 10^m * delta * 2^e
  680|       |    //                    p2 <= 10^m * delta
  681|  34.1M|    delta *= 10;
  682|  34.1M|    dist *= 10;
  683|  34.1M|    if (p2 <= delta) {
  ------------------
  |  Branch (683:9): [True: 2.62M, False: 31.4M]
  ------------------
  684|  2.62M|      break;
  685|  2.62M|    }
  686|  34.1M|  }
  687|       |
  688|       |  // V = buffer * 10^-m, with M- <= V <= M+.
  689|       |
  690|  2.62M|  decimal_exponent -= m;
  691|       |
  692|       |  // 1 ulp in the decimal representation is now 10^-m.
  693|       |  // Since delta and dist are now scaled by 10^m, we need to do the
  694|       |  // same with ulp in order to keep the units in sync.
  695|       |  //
  696|       |  //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
  697|       |  //
  698|  2.62M|  const std::uint64_t ten_m = one.f;
  699|  2.62M|  grisu2_round(buffer, length, dist, delta, p2, ten_m);
  700|       |
  701|       |  // By construction this algorithm generates the shortest possible decimal
  702|       |  // number (Loitsch, Theorem 6.2) which rounds back to w.
  703|       |  // For an input number of precision p, at least
  704|       |  //
  705|       |  //      N = 1 + ceil(p * log_10(2))
  706|       |  //
  707|       |  // decimal digits are sufficient to identify all binary floating-point
  708|       |  // numbers (Matula, "In-and-Out conversions").
  709|       |  // This implies that the algorithm does not produce more than N decimal
  710|       |  // digits.
  711|       |  //
  712|       |  //      N = 17 for p = 53 (IEEE double precision)
  713|       |  //      N = 9  for p = 24 (IEEE single precision)
  714|  2.62M|}
_ZN8simdjson8internal9dtoa_impl5diyfp3subERKS2_S4_:
   53|  5.44M|  static diyfp sub(const diyfp &x, const diyfp &y) noexcept {
   54|       |
   55|  5.44M|    return {x.f - y.f, x.e};
   56|  5.44M|  }
_ZN8simdjson8internal9dtoa_impl18find_largest_pow10EjRj:
  416|  2.72M|inline int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10) {
  417|       |  // LCOV_EXCL_START
  418|  2.72M|  if (n >= 1000000000) {
  ------------------
  |  Branch (418:7): [True: 0, False: 2.72M]
  ------------------
  419|      0|    pow10 = 1000000000;
  420|      0|    return 10;
  421|      0|  }
  422|       |  // LCOV_EXCL_STOP
  423|  2.72M|  else if (n >= 100000000) {
  ------------------
  |  Branch (423:12): [True: 2.47k, False: 2.72M]
  ------------------
  424|  2.47k|    pow10 = 100000000;
  425|  2.47k|    return 9;
  426|  2.72M|  } else if (n >= 10000000) {
  ------------------
  |  Branch (426:14): [True: 8.27k, False: 2.71M]
  ------------------
  427|  8.27k|    pow10 = 10000000;
  428|  8.27k|    return 8;
  429|  2.71M|  } else if (n >= 1000000) {
  ------------------
  |  Branch (429:14): [True: 16.4k, False: 2.69M]
  ------------------
  430|  16.4k|    pow10 = 1000000;
  431|  16.4k|    return 7;
  432|  2.69M|  } else if (n >= 100000) {
  ------------------
  |  Branch (432:14): [True: 4.87k, False: 2.69M]
  ------------------
  433|  4.87k|    pow10 = 100000;
  434|  4.87k|    return 6;
  435|  2.69M|  } else if (n >= 10000) {
  ------------------
  |  Branch (435:14): [True: 24.0k, False: 2.66M]
  ------------------
  436|  24.0k|    pow10 = 10000;
  437|  24.0k|    return 5;
  438|  2.66M|  } else if (n >= 1000) {
  ------------------
  |  Branch (438:14): [True: 2.57M, False: 90.5k]
  ------------------
  439|  2.57M|    pow10 = 1000;
  440|  2.57M|    return 4;
  441|  2.57M|  } else if (n >= 100) {
  ------------------
  |  Branch (441:14): [True: 55.7k, False: 34.7k]
  ------------------
  442|  55.7k|    pow10 = 100;
  443|  55.7k|    return 3;
  444|  55.7k|  } else if (n >= 10) {
  ------------------
  |  Branch (444:14): [True: 31.1k, False: 3.64k]
  ------------------
  445|  31.1k|    pow10 = 10;
  446|  31.1k|    return 2;
  447|  31.1k|  } else {
  448|  3.64k|    pow10 = 1;
  449|  3.64k|    return 1;
  450|  3.64k|  }
  451|  2.72M|}
_ZN8simdjson8internal9dtoa_impl12grisu2_roundEPcimmmm:
  455|  2.72M|                         std::uint64_t ten_k) {
  456|       |
  457|       |  //               <--------------------------- delta ---->
  458|       |  //                                  <---- dist --------->
  459|       |  // --------------[------------------+-------------------]--------------
  460|       |  //               M-                 w                   M+
  461|       |  //
  462|       |  //                                  ten_k
  463|       |  //                                <------>
  464|       |  //                                       <---- rest ---->
  465|       |  // --------------[------------------+----+--------------]--------------
  466|       |  //                                  w    V
  467|       |  //                                       = buf * 10^k
  468|       |  //
  469|       |  // ten_k represents a unit-in-the-last-place in the decimal representation
  470|       |  // stored in buf.
  471|       |  // Decrement buf by ten_k while this takes buf closer to w.
  472|       |
  473|       |  // The tests are written in this order to avoid overflow in unsigned
  474|       |  // integer arithmetic.
  475|       |
  476|  7.82M|  while (rest < dist && delta - rest >= ten_k &&
  ------------------
  |  Branch (476:10): [True: 7.65M, False: 172k]
  |  Branch (476:25): [True: 7.63M, False: 21.6k]
  ------------------
  477|  7.82M|         (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
  ------------------
  |  Branch (477:11): [True: 5.06M, False: 2.57M]
  |  Branch (477:34): [True: 40.7k, False: 2.52M]
  ------------------
  478|  5.10M|    buf[len - 1]--;
  479|  5.10M|    rest += ten_k;
  480|  5.10M|  }
  481|  2.72M|}

