• Seth Brenith's avatar
    [diagnostics] Support --turbo-profiling for builtins · 18c73676
    Seth Brenith authored
    Currently, if d8 is run with the --turbo-profiling flag, it prints info
    about every TurboFan-compiled function. This info includes the number of
    times that each basic block in the function was run. It also includes
    text representations of the function's schedule and code, so that the
    person reading the output can associate counters with blocks of code.
    
    The data about each function is currently stored in a
    BasicBlockProfiler::Data instance, which is attached to a list owned by
    the singleton BasicBlockProfiler. Each Data contains an
    std::vector<uint32_t> which represents how many times each block in the
    function has executed. The generated code for each block uses a raw
    pointer into the storage of that vector to implement incrementing the
    counter.
    
    With this change, if you compile with v8_enable_builtins_profiling and
    then run with --turbo-profiling, d8 will print that same info about
    builtins too.
    
    In order to generate code that can survive being serialized to a
    snapshot and reloaded, this change uses counters in the JS heap instead
    of a std::vector outside the JS heap. The steps for instrumentation are
    as follows:
    
    1. Between scheduling and instruction selection, add code to increment
       the counter for each block. The counters array doesn't yet exist at
       this point, and allocation is disallowed, so at this point the code
       refers to a special marker value.
    2. During finalization of the code, allocate a BasicBlockProfilingData
       object on the JS heap containing data equivalent to what is stored in
       BasicBlockProfiler::Data. This includes a ByteArray that is big
       enough to store the counters for each block.
    3. Patch the reference in the BuiltinsConstantsTableBuilder so that
       instead of referring to the marker object, it now refers to this
       ByteArray. Also add the BasicBlockProfilingData object to a list that
       is attached to the heap roots so it can be easily accessed for
       printing.
    
    Because these steps include modifying the BuiltinsConstantsTableBuilder,
    this procedure is only applicable to builtins. Runtime-generated code
    still uses raw pointers into std::vector instances. In order to keep
    divergence between these code paths to a minimum, most work is done
    referring to instances of BasicBlockProfiler::Data (the C++ class), and
    functions are provided to copy back and forth between that type and
    BasicBlockProfilingData (the JS heap object).
    
    This change is intended only to make --turbo-profiling work consistently
    on more kinds of functions, but with some further work, this data could
    form the basis for:
    - code coverage info for fuzzers, and/or
    - hot-path info for profile-guided optimization.
    
    Bug: v8:10470, v8:9119
    Change-Id: Ib556a5bc3abe67cdaa2e3ee62702a2a08b11cb61
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2159738
    Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
    Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
    Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#67944}
    18c73676