Skip to content
Snippets Groups Projects
Commit 3294afd2 authored by Julian Seward's avatar Julian Seward
Browse files

Bug 1725587 - SpiderMonkey `IONFLAGS=codegen` printing: hierarchical created-by markers. r=nbp.

This is an `#ifdef DEBUG` only patch and has no space or time effect on
non-debug builds.  It makes it easier to figure out which part of the SM suite
of code generators, stub generators, etc, created each instruction shown in
the `IONFLAGS=codegen` output.

In the base class of all assemblers, `js::jit::AssemblerShared`, there is a
new field `Vector<const char*> creators_`.  This is a small stack of arbitrary
strings.  Every time a string is pushed onto or popped off the stack, the
stack is printed in the `IONFLAGS=codegen` output.  Crucially, it is
debug-asserted that the stack is non-empty at emission of (almost) every
instruction.  Hence each instruction in the log output is bracketed within at
least one level of text-label.  By suitable choice of the labels, it is
possible to find which part of SM created an instruction with little
difficulty.

Pushing and popping the stack directly is strongly discouraged.  Instead, an
RAII `class AutoCreatedBy` is provided to manage the stack.  Adding
C++-scope-level annotations is then simply a matter of adding lines of the
form `AutoCreatedBy acb(masm, "my tag text");`.

The stacks resulting from the current annotation set have at most three
entries, for example:

  BaselineInterpreterGenerator::generate/interpreter loop/op=Uint24

The patch looks large but is really very simple.  There are the following
logical components, unfortunately interleaved in the patch:

* A large set of `AutoCreatedBy` annotations.  This gives complete coverage
  for code generation on x86, x64, arm, arm64 and mips64, as far as I can
  tell.  This is the vast majority of the patch.

* In `class AssemblerShared` (Assembler-shared.h), new field `creators_` and
  methods `{push,pop,has}Creator` to operate on it.

* Also in Assembler-shared.h, `class MOZ_RAII AutoCreatedBy`, to manage the
  stack.

* The assertions to ensure that the stack is not empty at emission of any
  instruction.

  - for arm64, this is done in `MozBaseAssembler::Emit` (two functions)

  - for arm, this is done in `Assembler::writeInst`

  - for mips64, this is done in `AssemblerMIPSShared::writeInst`

  - for x86 and x64 I failed to find any single place to put such an
    assertion, that also has convenient access to the required
    `AssemblerShared` base class.  Instead these have a best-effort solution:
    assertions have been added to around 20 methods in `AssemblerX86Shared`.
    These cover the most common instructions (loads, stores, reg-reg moves,
    pushes, pops, returns, immediate data, alignment directives).  Although
    this is not complete coverage, in practice it's good enough because it's
    almost impossible to create any piece of code without using at least one
    insn in that group.

Almost all of the implementation is guarded `#ifdef DEBUG`.  The one exception
is constructor `AutoCreatedBy::AutoCreatedBy`.  I did not want to uglify
dozens of places in SM with guards at all its use points.  So instead a dummy
release-build version has been provided:

  inline AutoCreatedBy(AssemblerShared& ash, const char* who) {}

on the basis that an optimising compiler will inline it away completely.

`AssemblerShared::pushCreator` ignores OOM conditions when pushing on the
stack.  This is assumed to be OK since this is a debug-build-only activity.

Differential Revision: https://phabricator.services.mozilla.com/D123854
parent c35fc5e1
No related branches found
No related tags found
No related merge requests found
Showing
with 236 additions and 2 deletions
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment