Backed out changeset 2592edffe5f4 (bug 1661256) for cppunit failure . CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Wed, 28 Oct 2020 19:42:07 +0200
changeset 554943 9b78e4ae32ae9fe7a22b4bb15efb51251d70c5e6
parent 554942 4ef5e2c8e4e41b9814d3d2b6abc346f5aa426957
child 554944 bae725214f5ac6126901d70e4d0f8935c261419d
push id129664
push usernbeleuzu@mozilla.com
push dateWed, 28 Oct 2020 17:42:31 +0000
treeherderautoland@9b78e4ae32ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1661256
milestone84.0a1
backs out2592edffe5f4a44c85d36c86c48f49abed0d7997
first release with
nightly linux32
9b78e4ae32ae / 84.0a1 / 20201028214727 / files
nightly linux64
9b78e4ae32ae / 84.0a1 / 20201028214727 / files
nightly mac
9b78e4ae32ae / 84.0a1 / 20201028214727 / files
nightly win32
9b78e4ae32ae / 84.0a1 / 20201028214727 / files
nightly win64
9b78e4ae32ae / 84.0a1 / 20201028214727 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 2592edffe5f4 (bug 1661256) for cppunit failure . CLOSED TREE
js/src/jit/ABIFunctions.h
js/src/jsapi-tests/moz.build
js/src/jsapi-tests/testJitABIcalls.cpp
--- a/js/src/jit/ABIFunctions.h
+++ b/js/src/jit/ABIFunctions.h
@@ -2,18 +2,16 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_ABIFunctions_h
 #define jit_ABIFunctions_h
 
-#include "jstypes.h" // JS_FUNC_TO_DATA_PTR
-
 namespace js {
 namespace jit {
 
 // This class is used to ensure that all known targets of callWithABI are
 // registered here. Otherwise, this would raise a static assertion at compile
 // time.
 template <typename Sig, Sig fun>
 struct ABIFunctionData {
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -132,17 +132,16 @@ SOURCES += [
 
 SOURCES += [
     # We don't want this in the C++ files with the test cases.
     "hidePointer.cpp",
 ]
 
 if not CONFIG["JS_CODEGEN_NONE"]:
     UNIFIED_SOURCES += [
-        "testJitABIcalls.cpp",
         "testJitDCEinGVN.cpp",
         "testJitFoldsTo.cpp",
         "testJitGVN.cpp",
         "testJitMacroAssembler.cpp",
         "testJitMoveEmitterCycles-mips32.cpp",
         "testJitMoveEmitterCycles.cpp",
         "testJitRangeAnalysis.cpp",
         "testJitRegisterSet.cpp",
deleted file mode 100644
--- a/js/src/jsapi-tests/testJitABIcalls.cpp
+++ /dev/null
@@ -1,739 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set ts=8 sts=2 et sw=2 tw=80:
- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/FloatingPoint.h"
-#include "mozilla/IntegerTypeTraits.h"
-
-#include "jit/ABIFunctions.h"
-#include "jit/IonAnalysis.h"
-#include "jit/Linker.h"
-#include "jit/MacroAssembler.h"
-#include "jit/MIRGenerator.h"
-#include "jit/MIRGraph.h"
-#include "jit/ValueNumbering.h"
-#include "jit/VMFunctions.h"
-#include "js/Value.h"
-
-#include "jsapi-tests/tests.h"
-
-#include "jit/ABIFunctionList-inl.h"
-#include "jit/MacroAssembler-inl.h"
-#include "jit/VMFunctionList-inl.h"
-
-using namespace js;
-using namespace js::jit;
-
-// This test case relies on VMFUNCTION_LIST, TAIL_CALL_VMFUNCTION_LIST,
-// ABIFUNCTION_LIST, ABIFUNCTION_AND_TYPE_LIST and ABIFUNCTIONSIG_LIST, to
-// create a test case for each function registered, in order to check if the
-// arguments are properly being interpreted after a call from the JIT.
-//
-// This test checks that the interpretation of the C++ compiler matches the
-// interpretation of the JIT. It works by generating a call to a function which
-// has the same signature as the tested function. The function being called
-// re-interprets the arguments' content to ensure that it matches the content
-// given as arguments by the JIT.
-//
-// These tests cases succeed if the content provided by the JIT matches the
-// content read by the C++ code. Otherwise, a failure implies that either the
-// MacroAssembler is not used properly, or that the code used by the JIT to
-// generate the function call does not match the ABI of the targeted system.
-
-// Convert the content of each macro list to a single and unique format which is
-// (Name, Type).
-#define ABIFUN_TO_ALLFUN(Fun) (#Fun, decltype(&::Fun))
-#define ABIFUN_AND_SIG_TO_ALLFUN(Fun, Sig) (#Fun " as " #Sig, Sig)
-#define ABISIG_TO_ALLFUN(Sig) ("(none) as " #Sig, Sig)
-#define VMFUN_TO_ALLFUN(Name, Fun) (#Fun, decltype(&::Fun))
-#define TC_VMFUN_TO_ALLFUN(Name, Fun, Pop) (#Fun, decltype(&::Fun))
-
-#define APPLY(A, B) A B
-
-// Generate macro calls for all the lists which are used to allow, directly or
-// indirectly, calls performed with callWithABI.
-//
-// This macro will delegate to a different macro call based on the type of the
-// list the element is extracted from.
-#define ALL_FUNCTIONS(PREFIX)                                  \
-  ABIFUNCTION_LIST(PREFIX##_ABIFUN_TO_ALLFUN)                  \
-  ABIFUNCTION_AND_TYPE_LIST(PREFIX##_ABIFUN_AND_SIG_TO_ALLFUN) \
-  ABIFUNCTIONSIG_LIST(PREFIX##_ABISIG_TO_ALLFUN)               \
-  VMFUNCTION_LIST(PREFIX##_VMFUN_TO_ALLFUN)                    \
-  TAIL_CALL_VMFUNCTION_LIST(PREFIX##_TC_VMFUN_TO_ALLFUN)
-
-// sizeof(const T&) is not equal to sizeof(const T*), but references are passed
-// as pointers.
-//
-// "When applied to a reference or a reference type, the result is the size of
-// the referenced type." [expr.sizeof] (5.3.3.2)
-//
-// The following functions avoid this issue by wrapping the type in a structure
-// which will share the same property, even if the wrapped type is a reference.
-template <typename T>
-constexpr size_t ActualSizeOf() {
-  struct Wrapper {
-    T _unused;
-  };
-  return sizeof(Wrapper);
-}
-
-template <typename T>
-constexpr size_t ActualAlignOf() {
-  struct Wrapper {
-    T _unused;
-  };
-  return alignof(Wrapper);
-}
-
-// Given a type, return the integer type which has the same size.
-template <typename T>
-using IntTypeOf_t =
-    typename mozilla::UnsignedStdintTypeForSize<ActualSizeOf<T>()>::Type;
-
-// Concatenate 2 std::integer_sequence, and return an std::integer_sequence with
-// the content of both parameters.
-template <typename Before, typename After>
-struct Concat;
-
-template <typename Int, Int... Before, Int... After>
-struct Concat<std::integer_sequence<Int, Before...>,
-              std::integer_sequence<Int, After...>> {
-  using type = std::integer_sequence<Int, Before..., After...>;
-};
-
-template <typename Before, typename After>
-using Concat_t = typename Concat<Before, After>::type;
-
-static_assert(std::is_same_v<Concat_t<std::integer_sequence<uint8_t, 1, 2>,
-                                      std::integer_sequence<uint8_t, 3, 4>>,
-                             std::integer_sequence<uint8_t, 1, 2, 3, 4>>);
-
-// Generate an std::integer_sequence of `N` elements, where each element is an
-// uint8_t integer with value `Value`.
-template <size_t N, uint8_t Value>
-constexpr auto CstSeq() {
-  if constexpr (N == 0) {
-    return std::integer_sequence<uint8_t>{};
-  } else {
-    return Concat_t<std::integer_sequence<uint8_t, Value>,
-                    decltype(CstSeq<N - 1, Value>())>{};
-  }
-}
-
-template <size_t N, uint8_t Value>
-using CstSeq_t = decltype(CstSeq<N, Value>());
-
-static_assert(
-    std::is_same_v<CstSeq_t<4, 2>, std::integer_sequence<uint8_t, 2, 2, 2, 2>>);
-
-// Computes the number of bytes to add before a type in order to align it in
-// memory.
-constexpr size_t PadBytes(size_t size, size_t align) {
-  return (align - (size % align)) % align;
-}
-
-// Request a minimum alignment for the values added to a buffer in order to
-// account for the read size used by the MoveOperand given as an argument of
-// passWithABI. The MoveOperand does not take into consideration the size of
-// the data being transfered, and might load a larger amount of data.
-//
-// This function ensures that the MoveOperand would read the 0x55 padding added
-// after each value, when it reads too much.
-constexpr size_t AtLeastSize() { return sizeof(uintptr_t); }
-
-// Returns the size which needs to be added in addition to the memory consumed
-// by the type, from which the size if given as argument.
-template <typename Type>
-constexpr size_t BackPadBytes() {
-  return std::max(AtLeastSize(), ActualSizeOf<Type>()) - ActualSizeOf<Type>();
-}
-
-// Adds the padding and the reserved size for storing a value in a buffer which
-// can be read by a MoveOperand.
-template <typename Type>
-constexpr size_t PadSize(size_t size) {
-  return PadBytes(size, ActualAlignOf<Type>()) + ActualSizeOf<Type>() +
-         BackPadBytes<Type>();
-}
-
-// Generate an std::integer_sequence of 0:uint8_t elements of the size of the
-// padding needed to align a type in memory.
-template <size_t Align, size_t CurrSize>
-using PadSeq_t = decltype(CstSeq<PadBytes(CurrSize, Align), 0>());
-
-static_assert(std::is_same_v<PadSeq_t<4, 0>, std::integer_sequence<uint8_t>>);
-static_assert(
-    std::is_same_v<PadSeq_t<4, 3>, std::integer_sequence<uint8_t, 0>>);
-static_assert(
-    std::is_same_v<PadSeq_t<4, 2>, std::integer_sequence<uint8_t, 0, 0>>);
-static_assert(
-    std::is_same_v<PadSeq_t<4, 1>, std::integer_sequence<uint8_t, 0, 0, 0>>);
-
-// Spread an integer value `Value` into a new std::integer_sequence of `N`
-// uint8_t elements, using Little Endian ordering of bytes.
-template <size_t N, uint64_t Value, uint8_t... Rest>
-constexpr auto FillLESeq() {
-  if constexpr (N == 0) {
-    return std::integer_sequence<uint8_t, Rest...>{};
-  } else {
-    return FillLESeq<N - 1, (Value >> 8), Rest..., uint8_t(Value & 0xff)>();
-  }
-}
-
-template <size_t N, uint64_t Value>
-using FillSeq_t = decltype(FillLESeq<N, Value>());
-
-static_assert(std::is_same_v<FillSeq_t<4, 2>,
-                             std::integer_sequence<uint8_t, 2, 0, 0, 0>>);
-
-// Given a list of template parameters, generate an std::integer_sequence of
-// size_t, where each element is 1 larger than the previous one. The generated
-// sequence starts at 0.
-template <typename... Args>
-using ArgsIndexes_t =
-    std::make_integer_sequence<uint64_t, uint64_t(sizeof...(Args))>;
-
-static_assert(std::is_same_v<ArgsIndexes_t<uint8_t, uint64_t>,
-                             std::integer_sequence<uint64_t, 0, 1>>);
-
-// Extract a single bit for each element of an std::integer_sequence. This is
-// used to work around some restrictions with providing boolean arguments,
-// which might be truncated to a single bit.
-template <size_t Bit, typename IntSeq>
-struct ExtractBit;
-
-template <size_t Bit, uint64_t... Values>
-struct ExtractBit<Bit, std::integer_sequence<uint64_t, Values...>> {
-  using type = std::integer_sequence<uint64_t, (Values >> Bit) & 1 ...>;
-};
-
-// Generate an std::integer_sequence of indexes which are filtered for a single
-// bit, such that it can be used with boolean types.
-template <size_t Bit, typename... Args>
-using ArgsBitOfIndexes_t =
-    typename ExtractBit<Bit, ArgsIndexes_t<Args...>>::type;
-
-static_assert(std::is_same_v<ArgsBitOfIndexes_t<0, int, int, int, int>,
-                             std::integer_sequence<uint64_t, 0, 1, 0, 1>>);
-static_assert(std::is_same_v<ArgsBitOfIndexes_t<1, int, int, int, int>,
-                             std::integer_sequence<uint64_t, 0, 0, 1, 1>>);
-
-// Compute the offset of each argument in a buffer produced by GenArgsBuffer,
-// this is used to fill the MoveOperand displacement field when loading value
-// out of the buffer produced by GenArgsBuffer.
-template <uint64_t Size, typename... Args>
-struct ArgsOffsets;
-
-template <uint64_t Size>
-struct ArgsOffsets<Size> {
-  using type = std::integer_sequence<uint64_t>;
-};
-
-template <uint64_t Size, typename Arg, typename... Args>
-struct ArgsOffsets<Size, Arg, Args...> {
-  using type = Concat_t<
-      std::integer_sequence<uint64_t, Size + PadBytes(Size, alignof(Arg))>,
-      typename ArgsOffsets<Size + PadSize<Arg>(Size), Args...>::type>;
-};
-
-template <uint64_t Size, typename... Args>
-using ArgsOffsets_t = typename ArgsOffsets<Size, Args...>::type;
-
-// Not all 32bits architecture align uint64_t type on 8 bytes, so check the
-// validity of the stored content based on the alignment of the architecture.
-static_assert(alignof(uint64_t) != 8 ||
-              std::is_same_v<ArgsOffsets_t<0, uint8_t, uint64_t, bool>,
-                             std::integer_sequence<uint64_t, 0, 8, 16>>);
-
-static_assert(alignof(uint64_t) != 4 ||
-              std::is_same_v<ArgsOffsets_t<0, uint8_t, uint64_t, bool>,
-                             std::integer_sequence<uint64_t, 0, 4, 12>>);
-
-// Generate an std::integer_sequence containing the size of each argument in
-// memory.
-template <typename... Args>
-using ArgsSizes_t = std::integer_sequence<uint64_t, ActualSizeOf<Args>()...>;
-
-// Generate an std::integer_sequence containing values where all valid bits for
-// each type are set to 1.
-template <typename Type>
-constexpr uint64_t FillBits() {
-  constexpr uint64_t topBit = uint64_t(1) << ((8 * ActualSizeOf<Type>()) - 1);
-  if constexpr (std::is_same_v<Type, bool>) {
-    return uint64_t(1);
-  } else if constexpr (std::is_same_v<Type, double> ||
-                       std::is_same_v<Type, float>) {
-    // A NaN has all the bits of its exponent set to 1. The CPU / C++ does not
-    // garantee keeping the payload of NaN values, when interpreted as floating
-    // point, which could cause some random failures. This removes one bit from
-    // the exponent, such that the floating point value is not converted to a
-    // canonicalized NaN by the time we compare it.
-    constexpr uint64_t lowExpBit =
-        uint64_t(1) << mozilla::FloatingPoint<Type>::kExponentShift;
-    return uint64_t((topBit - 1) + topBit - lowExpBit);
-  } else {
-    // Note: Keep parantheses to avoid unwanted overflow.
-    return uint64_t((topBit - 1) + topBit);
-  }
-}
-
-template <typename... Args>
-using ArgsFillBits_t = std::integer_sequence<uint64_t, FillBits<Args>()...>;
-
-// Given a type, return the MoveOp type used by passABIArg to know how to
-// interpret the value which are given as arguments.
-template <typename Type>
-constexpr MoveOp::Type TypeToMoveOp() {
-  if constexpr (std::is_same_v<Type, float>) {
-    return MoveOp::FLOAT32;
-  } else if constexpr (std::is_same_v<Type, double>) {
-    return MoveOp::DOUBLE;
-  } else {
-    return MoveOp::GENERAL;
-  }
-}
-
-// Generate a sequence which contains the associated MoveOp of each argument.
-// Note, a new class is defined because C++ header of clang are rejecting the
-// option of having an enumerated type as argument of std::integer_sequence.
-template <MoveOp::Type... Val>
-class MoveOpSequence {};
-
-template <typename... Args>
-using ArgsMoveOps_t = MoveOpSequence<TypeToMoveOp<Args>()...>;
-
-// Generate an std::integer_sequence which corresponds to a buffer containing
-// values which are spread at the location where each arguments type would be
-// stored in a buffer.
-template <typename Buffer, typename Values, typename... Args>
-struct ArgsBuffer;
-
-template <uint8_t... Buffer, typename Arg, typename... Args, uint64_t Val,
-          uint64_t... Values>
-struct ArgsBuffer<std::integer_sequence<uint8_t, Buffer...>,
-                  std::integer_sequence<uint64_t, Val, Values...>, Arg,
-                  Args...> {
-  using type = typename ArgsBuffer<
-      Concat_t<std::integer_sequence<uint8_t, Buffer...>,
-               Concat_t<PadSeq_t<ActualAlignOf<Arg>(), sizeof...(Buffer)>,
-                        Concat_t<FillSeq_t<ActualSizeOf<Arg>(), Val>,
-                                 CstSeq_t<BackPadBytes<Arg>(), 0x55>>>>,
-      std::integer_sequence<uint64_t, Values...>, Args...>::type;
-};
-
-template <typename Buffer>
-struct ArgsBuffer<Buffer, std::integer_sequence<uint64_t>> {
-  using type = Buffer;
-};
-
-template <typename Values, typename... Args>
-using ArgsBuffer_t =
-    typename ArgsBuffer<std::integer_sequence<uint8_t>, Values, Args...>::type;
-
-// NOTE: The representation of the boolean might be surprising in this test
-// case, see AtLeastSize function for an explanation.
-#ifdef JS_64BIT
-static_assert(sizeof(uintptr_t) == 8);
-static_assert(
-    std::is_same_v<
-        ArgsBuffer_t<std::integer_sequence<uint64_t, 42, 51>, uint64_t, bool>,
-        std::integer_sequence<uint8_t, 42, 0, 0, 0, 0, 0, 0, 0, 51, 0x55, 0x55,
-                              0x55, 0x55, 0x55, 0x55, 0x55>>);
-static_assert(
-    std::is_same_v<
-        ArgsBuffer_t<std::integer_sequence<uint64_t, 0xffffffff, 0xffffffff>,
-                     uint8_t, uint16_t>,
-        std::integer_sequence<uint8_t, 0xff, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
-                              0x55, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x55,
-                              0x55>>);
-#else
-static_assert(sizeof(uintptr_t) == 4);
-static_assert(
-    std::is_same_v<
-        ArgsBuffer_t<std::integer_sequence<uint64_t, 42, 51>, uint64_t, bool>,
-        std::integer_sequence<uint8_t, 42, 0, 0, 0, 0, 0, 0, 0, 51, 0x55, 0x55,
-                              0x55>>);
-static_assert(
-    std::is_same_v<
-        ArgsBuffer_t<std::integer_sequence<uint64_t, 0xffffffff, 0xffffffff>,
-                     uint8_t, uint16_t>,
-        std::integer_sequence<uint8_t, 0xff, 0x55, 0x55, 0x55, 0xff, 0xff, 0x55,
-                              0x55>>);
-#endif
-
-// Test used to check if any of the types given as template parameters are a
-// `bool`, which is a corner case where a raw integer might be truncated by the
-// C++ compiler.
-template <typename... Args>
-constexpr bool AnyBool_v = (std::is_same_v<Args, bool> || ...);
-
-// Instantiate an std::integer_sequence as a buffer which is readable and
-// addressable at runtime, for reading argument values from the generated code.
-template <typename Seq>
-struct InstanceSeq;
-
-template <typename Int, Int... Values>
-struct InstanceSeq<std::integer_sequence<Int, Values...>> {
-  static constexpr Int table[sizeof...(Values)] = {Values...};
-  static constexpr size_t size = sizeof...(Values);
-};
-
-// Instantiate a buffer for testing the position of arguments when calling a
-// function.
-template <typename... Args>
-using TestArgsPositions =
-    InstanceSeq<ArgsBuffer_t<ArgsIndexes_t<Args...>, Args...>>;
-
-// Instantiate a buffer for testing the position of arguments, one bit at a
-// time, when calling a function.
-template <size_t Bit, typename... Args>
-using TestArgsBitOfPositions =
-    InstanceSeq<ArgsBuffer_t<ArgsBitOfIndexes_t<Bit, Args...>, Args...>>;
-
-// Instantiate a buffer to check that the size of each argument is interpreted
-// correctly when calling a function.
-template <typename... Args>
-using TestArgsSizes = InstanceSeq<ArgsBuffer_t<ArgsSizes_t<Args...>, Args...>>;
-
-// Instantiate a buffer to check that all bits of each argument goes through.
-template <typename... Args>
-using TestArgsFillBits =
-    InstanceSeq<ArgsBuffer_t<ArgsFillBits_t<Args...>, Args...>>;
-
-// ConvertToInt returns the raw value of any argument as an integer value which
-// can be compared with the expected values.
-template <typename Type>
-IntTypeOf_t<Type> ConvertToInt(Type v) {
-  // Simplify working with types by casting the address of the value to the
-  // equivalent `const void*`.
-  auto address = reinterpret_cast<const void*>(&v);
-  // Convert the `void*` to an integer pointer of the same size as the input
-  // type, and return the raw value stored in the integer interpretation.
-  static_assert(ActualSizeOf<Type>() == ActualSizeOf<IntTypeOf_t<Type>>());
-  if constexpr (std::is_reference_v<Type>) {
-    return reinterpret_cast<const IntTypeOf_t<Type>>(address);
-  } else {
-    return *reinterpret_cast<const IntTypeOf_t<Type>*>(address);
-  }
-}
-
-// Check if the raw values of arguments are equal to the numbers given in the
-// std::integer_sequence given as the first argument.
-template <typename... Args, typename Int, Int... Val>
-bool CheckArgsEqual(JSAPITest* instance, int lineno,
-                    std::integer_sequence<Int, Val...>, Args... args) {
-  return (instance->checkEqual(ConvertToInt<Args>(args), IntTypeOf_t<Args>(Val),
-                               "ConvertToInt<Args>(args)",
-                               "IntTypeOf_t<Args>(Val)",
-                               __FILE__, lineno) && ...);
-}
-
-// Generate code to register the value of each argument of the called function.
-// Each argument's content is read from a buffer whose address is stored in the
-// `base` register. The offsets of arguments are given as a third argument
-// which is expected to be generated by `ArgsOffsets`. The MoveOp types of
-// arguments are given as the fourth argument and are expected to be generated
-// by `ArgsMoveOp`.
-template <uint64_t... Off, MoveOp::Type... Move>
-static void passABIArgs(MacroAssembler& masm, Register base,
-                        std::integer_sequence<uint64_t, Off...>,
-                        MoveOpSequence<Move...>) {
-  (masm.passABIArg(MoveOperand(base, size_t(Off)), Move), ...);
-}
-
-// For each function type given as a parameter, create a few functions with the
-// given type, to be called by the JIT code produced by `generateCalls`. These
-// functions report the result through the instance registered with the
-// `set_instance` function, as we cannot add extra arguments to these functions.
-template <typename Type>
-struct DefineCheckArgs;
-
-template <typename Res, typename... Args>
-struct DefineCheckArgs<Res (*)(Args...)> {
-  void set_instance(JSAPITest* instance, bool* reportTo) {
-    MOZ_ASSERT((!instance_) != (!instance));
-    instance_ = instance;
-    MOZ_ASSERT((!reportTo_) != (!reportTo));
-    reportTo_ = reportTo;
-  }
-  static void report(bool value) {
-    *reportTo_ = *reportTo_ && value;
-  }
-
-  // Check that arguments are interpreted in the same order at compile time and
-  // at runtime.
-  static Res CheckArgsPositions(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Indexes = std::index_sequence_for<Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Indexes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  // This is the same test as above, but some compilers might clean the boolean
-  // values using `& 1` operations, which corrupt the operand index, thus to
-  // properly check for the position of boolean operands, we have to check the
-  // position of the boolean operand using a single bit at a time.
-  static Res CheckArgsBitOfPositions0(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Indexes = ArgsBitOfIndexes_t<0, Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Indexes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  static Res CheckArgsBitOfPositions1(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Indexes = ArgsBitOfIndexes_t<1, Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Indexes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  static Res CheckArgsBitOfPositions2(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Indexes = ArgsBitOfIndexes_t<2, Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Indexes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  static Res CheckArgsBitOfPositions3(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Indexes = ArgsBitOfIndexes_t<3, Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Indexes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  // Check that the compile time and run time sizes of each argument are the
-  // same.
-  static Res CheckArgsSizes(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using Sizes = ArgsSizes_t<Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, Sizes(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  // Check that the compile time and run time all bits of each argument are
-  // correctly passed through.
-  static Res CheckArgsFillBits(Args... args) {
-    AutoUnsafeCallWithABI unsafe;
-    using FillBits = ArgsFillBits_t<Args...>;
-    report(CheckArgsEqual<Args...>(instance_, __LINE__, FillBits(),
-                                   std::forward<Args>(args)...));
-    return Res();
-  }
-
-  using FunType = Res (*)(Args...);
-  struct Test {
-    const uint8_t* buffer;
-    const size_t size;
-    const FunType fun;
-  };
-
-  // Generate JIT code for calling the above test functions where each argument
-  // is given a different raw value that can be compared by each called
-  // function.
-  void generateCalls(MacroAssembler& masm, Register base, Register setup) {
-    using ArgsPositions = TestArgsPositions<Args...>;
-    using ArgsBitOfPositions0 = TestArgsBitOfPositions<0, Args...>;
-    using ArgsBitOfPositions1 = TestArgsBitOfPositions<1, Args...>;
-    using ArgsBitOfPositions2 = TestArgsBitOfPositions<2, Args...>;
-    using ArgsBitOfPositions3 = TestArgsBitOfPositions<3, Args...>;
-    using ArgsSizes = TestArgsSizes<Args...>;
-    using ArgsFillBits = TestArgsFillBits<Args...>;
-    static const Test testsWithoutBoolArgs[3] = {
-        {ArgsPositions::table, ArgsPositions::size, CheckArgsPositions},
-        {ArgsSizes::table, ArgsSizes::size, CheckArgsSizes},
-        {ArgsFillBits::table, ArgsFillBits::size, CheckArgsFillBits},
-    };
-    static const Test testsWithBoolArgs[6] = {
-        {ArgsBitOfPositions0::table, ArgsBitOfPositions0::size,
-         CheckArgsBitOfPositions0},
-        {ArgsBitOfPositions1::table, ArgsBitOfPositions1::size,
-         CheckArgsBitOfPositions1},
-        {ArgsBitOfPositions2::table, ArgsBitOfPositions2::size,
-         CheckArgsBitOfPositions2},
-        {ArgsBitOfPositions3::table, ArgsBitOfPositions3::size,
-         CheckArgsBitOfPositions3},
-        {ArgsSizes::table, ArgsSizes::size, CheckArgsSizes},
-        {ArgsFillBits::table, ArgsFillBits::size, CheckArgsFillBits},
-    };
-    const Test* tests = testsWithoutBoolArgs;
-    size_t numTests = sizeof(testsWithoutBoolArgs) / sizeof(Test);
-    if (AnyBool_v<Args...>) {
-      tests = testsWithBoolArgs;
-      numTests = sizeof(testsWithBoolArgs) / sizeof(Test);
-    }
-
-    for (size_t i = 0; i < numTests; i++) {
-      const Test& test = tests[i];
-      masm.movePtr(ImmPtr(test.buffer), base);
-
-      masm.setupUnalignedABICall(setup);
-      using Offsets = ArgsOffsets_t<0, Args...>;
-      using MoveOps = ArgsMoveOps_t<Args...>;
-      passABIArgs(masm, base, Offsets(), MoveOps());
-      masm.callWithABI(DynFn{JS_FUNC_TO_DATA_PTR(void*, test.fun)},
-                       TypeToMoveOp<Res>(),
-                       CheckUnsafeCallWithABI::DontCheckOther);
-    }
-  }
-
- private:
-  // As we are checking specific function signature, we cannot add extra
-  // parameters, thus we rely on static variables to pass the value of the
-  // instance that we are testing.
-  static JSAPITest* instance_;
-  static bool* reportTo_;
-};
-
-template <typename Res, typename... Args>
-JSAPITest* DefineCheckArgs<Res (*)(Args...)>::instance_ = nullptr;
-
-template <typename Res, typename... Args>
-bool* DefineCheckArgs<Res (*)(Args...)>::reportTo_ = nullptr;
-
-typedef void (*EnterTest)();
-
-// On entry to the JIT code, save every register.
-static void Prepare(MacroAssembler& masm) {
-#if defined(JS_CODEGEN_ARM64)
-  masm.Mov(PseudoStackPointer64, sp);
-  masm.SetStackPointer64(PseudoStackPointer64);
-#endif
-  AllocatableRegisterSet regs(RegisterSet::All());
-  LiveRegisterSet save(regs.asLiveSet());
-  masm.PushRegsInMask(save);
-}
-
-// Generate the exit path of the JIT code, which restores every register. Then,
-// make it executable and run it.
-static bool Execute(JSContext* cx, MacroAssembler& masm) {
-  AllocatableRegisterSet regs(RegisterSet::All());
-  LiveRegisterSet save(regs.asLiveSet());
-  masm.PopRegsInMask(save);
-#if defined(JS_CODEGEN_ARM64)
-  // Return using the value popped into x30.
-  masm.abiret();
-
-  // Reset stack pointer.
-  masm.SetStackPointer64(PseudoStackPointer64);
-#else
-  masm.ret();  // Add return statement to be sure.
-#endif
-
-  if (masm.oom()) {
-    return false;
-  }
-
-  Linker linker(masm);
-  JitCode* code = linker.newCode(cx, CodeKind::Other);
-  if (!code) {
-    return false;
-  }
-  if (!ExecutableAllocator::makeExecutableAndFlushICache(
-          FlushICacheSpec::LocalThreadOnly, code->raw(), code->bufferSize())) {
-    return false;
-  }
-
-  JS::AutoSuppressGCAnalysis suppress;
-  EnterTest test = code->as<EnterTest>();
-  test();
-  return true;
-}
-
-// This is a child class of JSAPITest, which is used behind the scenes to
-// register test cases in jsapi-tests. Each instance of it creates a new test
-// case. This class is specialized with the type of the function to check, and
-// initialized with the name of the function with the given signature.
-//
-// When executed, it generates the JIT code to call functions with the same
-// signature and checks that the JIT interpretation of arguments location
-// matches the C++ interpretation. If it differs, the test case will fail.
-template <typename Sig>
-class JitABICall final : public JSAPITest, public DefineCheckArgs<Sig> {
- public:
-  explicit JitABICall(const char* name) : name_(name) { reuseGlobal = true; }
-  virtual const char* name() override { return name_; }
-  virtual bool run(JS::HandleObject) override {
-    bool result = true;
-    this->set_instance(this, &result);
-
-    StackMacroAssembler masm(cx);
-    Prepare(masm);
-
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
-    // Initialize the base register the same way this is done while reading
-    // arguments in generateVMWrapper, in order to avoid MOZ_RELEASE_ASSERT in
-    // the MoveResolver.
-#if defined(JS_CODEGEN_X86)
-    Register base = regs.takeAny();
-#elif defined(JS_CODEGEN_X64)
-    Register base = r10;
-    regs.take(base);
-#elif defined(JS_CODEGEN_ARM)
-    Register base = r5;
-    regs.take(base);
-#elif defined(JS_CODEGEN_ARM64)
-    Register base = r8;
-    regs.take(base);
-#elif defined(JS_CODEGEN_MIPS32)
-    Register base = t1;
-    regs.take(base);
-#elif defined(JS_CODEGEN_MIPS64)
-    Register base = t1;
-    regs.take(base);
-#else
-#  error "Unknown architecture!"
-#endif
-
-    Register setup = regs.takeAny();
-
-    this->generateCalls(masm, base, setup);
-
-    if (!Execute(cx, masm)) {
-      return false;
-    }
-    this->set_instance(nullptr, nullptr);
-    return result;
-  };
-
- private:
-  const char* name_;
-};
-
-// GCC warns when the signature does not have matching attributes (for example
-// MOZ_MUST_USE). Squelch this warning to avoid a GCC-only footgun.
-#if MOZ_IS_GCC
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wignored-attributes"
-#endif
-
-// For each VMFunction and ABIFunction, create an instance of a JitABICall
-// class to register a jsapi-tests test case.
-#define TEST_INSTANCE(Name, Sig)                                             \
-  static JitABICall<Sig> MOZ_CONCAT(MOZ_CONCAT(cls_jitabicall, __COUNTER__), \
-                                    _instance)("JIT ABI for " Name);
-#define TEST_INSTANCE_ABIFUN_TO_ALLFUN(...) \
-  APPLY(TEST_INSTANCE, ABIFUN_TO_ALLFUN(__VA_ARGS__))
-#define TEST_INSTANCE_ABIFUN_AND_SIG_TO_ALLFUN(...) \
-  APPLY(TEST_INSTANCE, ABIFUN_AND_SIG_TO_ALLFUN(__VA_ARGS__))
-#define TEST_INSTANCE_ABISIG_TO_ALLFUN(...) \
-  APPLY(TEST_INSTANCE, ABISIG_TO_ALLFUN(__VA_ARGS__))
-#define TEST_INSTANCE_VMFUN_TO_ALLFUN(...) \
-  APPLY(TEST_INSTANCE, VMFUN_TO_ALLFUN(__VA_ARGS__))
-#define TEST_INSTANCE_TC_VMFUN_TO_ALLFUN(...) \
-  APPLY(TEST_INSTANCE, TC_VMFUN_TO_ALLFUN(__VA_ARGS__))
-
-ALL_FUNCTIONS(TEST_INSTANCE)
-
-#if MOZ_IS_GCC
-#  pragma GCC diagnostic pop
-#endif