Created
October 2, 2020 21:12
-
-
Save hotsphink/6b10862d9d6c978e91a2f06b66a0e11d to your computer and use it in GitHub Desktop.
mkgist-created gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601504771 25200 | |
# Wed Sep 30 15:26:11 2020 -0700 | |
# Node ID d2658c507732fb666d515e5bbe04912e91026e9a | |
# Parent f9261c82b0dd868417bf1eacfeda465a1542bc38 | |
VoidStarOf is unnecessary. Just cast to `const void*`. | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -98,33 +98,16 @@ struct WrapForSizeOf { | |
}; | |
// Given a type, return the integer type which has the same size. | |
template <typename T> | |
struct IntTypeOf { | |
using Res = typename IntBySize<sizeof(WrapForSizeOf<T>)>::Res; | |
}; | |
-// Given a type, return a void pointer type with the same `const` qualifier. | |
-// This is used to later remove the const qualifier if any. | |
-template <typename T> | |
-struct VoidStarOf { | |
- using Res = void*; | |
-}; | |
- | |
-template <typename T> | |
-struct VoidStarOf<const T> { | |
- using Res = const void*; | |
-}; | |
- | |
-template <typename T> | |
-struct VoidStarOf<const T&> { | |
- using Res = const void*; | |
-}; | |
- | |
// 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...>> { | |
@@ -376,42 +359,38 @@ using TestArgsSizes = InstanceSeq< | |
typename ArgsBuffer<typename ArgsSizes<Args...>::Res, Args...>::Res>; | |
// AsInt returns the raw value of any argument as an integer value which can be | |
// compared with the expected values. | |
template <typename Type> | |
struct AsInt { | |
static typename IntTypeOf<Type>::Res Convert(Type v) { | |
// Simplify working with types by casting the address of the value to the | |
- // equivalent `void*` / `const void*`. | |
- auto addr = reinterpret_cast<typename VoidStarOf<Type>::Res>(&v); | |
- // Remove the const from `const void*` if any. | |
- void* address = const_cast<void*>(addr); | |
+ // 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(sizeof(WrapForSizeOf<Type>) == | |
sizeof(WrapForSizeOf<typename IntTypeOf<Type>::Res>)); | |
- return *reinterpret_cast<typename IntTypeOf<Type>::Res*>(address); | |
+ return *reinterpret_cast<const typename IntTypeOf<Type>::Res*>(address); | |
} | |
}; | |
template <typename T> | |
struct AsInt<T&> { | |
using Type = T&; | |
static typename IntTypeOf<Type>::Res Convert(Type v) { | |
// Simplify working with types by casting the address of the value to the | |
- // equivalent `void*` / `const void*`. | |
- auto addr = reinterpret_cast<typename VoidStarOf<Type>::Res>(&v); | |
- // Remove the const from `const void*` if any. | |
- void* address = const_cast<void*>(addr); | |
+ // 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(sizeof(WrapForSizeOf<Type>) == | |
sizeof(WrapForSizeOf<typename IntTypeOf<Type>::Res>)); | |
- return reinterpret_cast<typename IntTypeOf<Type>::Res>(address); | |
+ return reinterpret_cast<const typename IntTypeOf<Type>::Res>(address); | |
} | |
}; | |
template <typename Type> | |
typename IntTypeOf<Type>::Res ConvertToInt(Type v) { | |
return AsInt<Type>::Convert(std::forward<Type>(v)); | |
} | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601672191 25200 | |
# Fri Oct 02 13:56:31 2020 -0700 | |
# Node ID cee51d93f57a7cd37195a357d7c17bb0cd9e16fc | |
# Parent d2658c507732fb666d515e5bbe04912e91026e9a | |
First, I don't really like the name `Res`, especially since it's sometimes used for types and sometimes for values. For that, it seems preferable to use the `std` notation of `type`/`value`. | |
But also, the boilerplate of `typename SomeTemplate<...>::Res` is really verbose and makes things hard to read. So I switched lots of stuff to using the c++14 TEMPLATE_t and TEMPLATE_v conventions, so that the above is now `SomeTemplate_v<...>`. | |
This patch changes most but not all of them. I wanted to change enough that I could see how it would read after the change. | |
With your capitalization scheme, it would probably be better to use `Type` and `Value` in place of `type`/`value`. I used the latter to match `std`, but in retrospect that's probably not all that important. Use whichever you prefer. | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -63,85 +63,93 @@ using namespace js::jit; | |
TAIL_CALL_VMFUNCTION_LIST(PREFIX##_TC_VMFUN_TO_ALLFUN) | |
// Given the size in bytes of a type, return the matching integer type. | |
template <size_t I> | |
struct IntBySize; | |
template <> | |
struct IntBySize<1> { | |
- using Res = uint8_t; | |
+ using type = uint8_t; | |
}; | |
template <> | |
struct IntBySize<2> { | |
- using Res = uint16_t; | |
+ using type = uint16_t; | |
}; | |
template <> | |
struct IntBySize<4> { | |
- using Res = uint32_t; | |
+ using type = uint32_t; | |
}; | |
template <> | |
struct IntBySize<8> { | |
- using Res = uint64_t; | |
+ using type = uint64_t; | |
}; | |
// sizeof(const T&) is not equal to sizeof(const T*). This structure is used to | |
// wrap the type which size is being queried, instead of the size of the type | |
// referenced by it. | |
// | |
// "When applied to a reference or a reference type, the result is the size of | |
// the referenced type." [expr.sizeof] (5.3.3.2) | |
template <typename T> | |
struct WrapForSizeOf { | |
T unused_; | |
}; | |
// Given a type, return the integer type which has the same size. | |
template <typename T> | |
struct IntTypeOf { | |
- using Res = typename IntBySize<sizeof(WrapForSizeOf<T>)>::Res; | |
+ using type = typename IntBySize<sizeof(WrapForSizeOf<T>)>::type; | |
}; | |
+template <typename T> | |
+using IntTypeOf_t = typename IntTypeOf<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 Res = std::integer_sequence<Int, Before..., After...>; | |
+ using type = std::integer_sequence<Int, Before..., After...>; | |
}; | |
-static_assert( | |
- std::is_same<typename Concat<std::integer_sequence<uint8_t, 1, 2>, | |
- std::integer_sequence<uint8_t, 3, 4>>::Res, | |
- std::integer_sequence<uint8_t, 1, 2, 3, 4>>::value); | |
+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 integers with value `Value`. | |
template <size_t N, uint8_t Value> | |
struct CstSeq { | |
- using Res = typename Concat<typename CstSeq<N / 2, Value>::Res, | |
- typename CstSeq<N - N / 2, Value>::Res>::Res; | |
+ using type = Concat_t<typename CstSeq<N / 2, Value>::type, | |
+ typename CstSeq<N - N / 2, Value>::type>; | |
}; | |
template <uint8_t Value> | |
struct CstSeq<0, Value> { | |
- using Res = std::integer_sequence<uint8_t>; | |
+ using type = std::integer_sequence<uint8_t>; | |
}; | |
template <uint8_t Value> | |
struct CstSeq<1, Value> { | |
- using Res = std::integer_sequence<uint8_t, Value>; | |
+ using type = std::integer_sequence<uint8_t, Value>; | |
}; | |
+template <size_t N, uint8_t Value> | |
+using CstSeq_t = typename CstSeq<N, Value>::type; | |
+ | |
// Computes the number of bytes to add before a type in order to align it in | |
// memory. | |
#define PADDING(SIZE, ALIGN) ((ALIGN) - ((SIZE) % (ALIGN))) % (ALIGN) | |
// Request a minimum alignment for the values which are added in a buffer, in | |
// order to account for the read size used by the MoveOperand given as argument | |
// of passWithABI. The MoveOperand do not take into consideration the size of | |
// the data which is being transfered, and might load a larger amount of data. | |
@@ -157,104 +165,114 @@ struct CstSeq<1, Value> { | |
PADDING(Size, alignof(WrapForSizeOf<TYPE>)) + \ | |
AT_LEAST_SIZE(sizeof(WrapForSizeOf<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 = CstSeq<PADDING(CurrSize, Align), 0>; | |
-static_assert(std::is_same<typename PadSeq<4, 0>::Res, | |
- std::integer_sequence<uint8_t>>::value); | |
-static_assert(std::is_same<typename PadSeq<4, 3>::Res, | |
- std::integer_sequence<uint8_t, 0>>::value); | |
-static_assert(std::is_same<typename PadSeq<4, 2>::Res, | |
- std::integer_sequence<uint8_t, 0, 0>>::value); | |
-static_assert(std::is_same<typename PadSeq<4, 1>::Res, | |
- std::integer_sequence<uint8_t, 0, 0, 0>>::value); | |
+template <size_t Align, size_t CurrSize> | |
+using PadSeq_t = typename PadSeq<Align, CurrSize>::type; | |
+ | |
+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, size_t Value, uint8_t... Rest> | |
struct FillLESeq { | |
- using Res = typename FillLESeq<N - 1, (Value >> 8), Rest..., | |
- uint8_t(Value & 0xff)>::Res; | |
+ using type = typename FillLESeq<N - 1, (Value >> 8), Rest..., | |
+ uint8_t(Value & 0xff)>::type; | |
}; | |
template <size_t Value, uint8_t... Rest> | |
struct FillLESeq<0, Value, Rest...> { | |
- using Res = std::integer_sequence<uint8_t, Rest...>; | |
+ using type = std::integer_sequence<uint8_t, Rest...>; | |
}; | |
template <size_t N, size_t Value> | |
using FillSeq = FillLESeq<N, Value>; | |
-static_assert(std::is_same<typename FillSeq<4, 2>::Res, | |
- std::integer_sequence<uint8_t, 2, 0, 0, 0>>::value); | |
+static_assert(std::is_same_v<typename FillSeq<4, 2>::type, | |
+ 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> | |
struct ArgsIndexes { | |
- using Res = std::index_sequence_for<Args...>; | |
+ using type = std::index_sequence_for<Args...>; | |
}; | |
-static_assert(std::is_same<typename ArgsIndexes<uint8_t, uint64_t>::Res, | |
- std::integer_sequence<size_t, 0, 1>>::value); | |
+static_assert(std::is_same_v<typename ArgsIndexes<uint8_t, uint64_t>::type, | |
+ std::integer_sequence<size_t, 0, 1>>); | |
// Extract a single bit for each element of an std::integer_sequence. This is | |
// used to work-around some restriction around providing boolean arguments, | |
// which might be truncated to a single bit. | |
template <size_t Bit, typename IntSeq> | |
struct ExtractBit; | |
template <size_t Bit, size_t... Values> | |
struct ExtractBit<Bit, std::integer_sequence<size_t, Values...>> { | |
- using Res = std::integer_sequence<size_t, (Values >> Bit) & 1 ...>; | |
+ using type = std::integer_sequence<size_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 = ExtractBit<Bit, typename ArgsIndexes<Args...>::Res>; | |
+using ArgsBitOfIndexes = ExtractBit<Bit, typename ArgsIndexes<Args...>::type>; | |
-static_assert(std::is_same<typename ArgsBitOfIndexes<0, int, int, int, int>::Res, | |
- std::integer_sequence<size_t, 0, 1, 0, 1>>::value); | |
-static_assert(std::is_same<typename ArgsBitOfIndexes<1, int, int, int, int>::Res, | |
- std::integer_sequence<size_t, 0, 0, 1, 1>>::value); | |
+static_assert( | |
+ std::is_same_v<typename ArgsBitOfIndexes<0, int, int, int, int>::type, | |
+ std::integer_sequence<size_t, 0, 1, 0, 1>>); | |
+static_assert( | |
+ std::is_same_v<typename ArgsBitOfIndexes<1, int, int, int, int>::type, | |
+ std::integer_sequence<size_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 <size_t Size, typename... Args> | |
struct ArgsOffsets; | |
template <size_t Size> | |
struct ArgsOffsets<Size> { | |
- using Res = std::integer_sequence<size_t>; | |
+ using type = std::integer_sequence<size_t>; | |
}; | |
template <size_t Size, typename Arg, typename... Args> | |
struct ArgsOffsets<Size, Arg, Args...> { | |
- using Res = typename Concat< | |
+ using type = Concat_t< | |
std::integer_sequence<size_t, Size + PADDING(Size, alignof(Arg))>, | |
- typename ArgsOffsets<Size + PADSIZE(Size, Arg), Args...>::Res>::Res; | |
+ typename ArgsOffsets<Size + PADSIZE(Size, Arg), Args...>::type>; | |
}; | |
-static_assert(std::is_same<typename ArgsOffsets<0, uint8_t, uint64_t, bool>::Res, | |
- std::integer_sequence<size_t, 0, 8, 16>>::value); | |
+template <size_t Size, typename... Args> | |
+using ArgsOffsets_t = typename ArgsOffsets<Size, Args...>::type; | |
+ | |
+static_assert(std::is_same_v<ArgsOffsets_t<0, uint8_t, uint64_t, bool>, | |
+ std::integer_sequence<size_t, 0, 8, 16>>); | |
// Generate an std::integer_sequence containing the size of each argument in | |
// memory. | |
template <typename... Args> | |
struct ArgsSizes { | |
- using Res = std::integer_sequence<size_t, sizeof(WrapForSizeOf<Args>)...>; | |
+ using type = std::integer_sequence<size_t, sizeof(WrapForSizeOf<Args>)...>; | |
}; | |
+template <typename... Args> | |
+using ArgsSizes_t = typename ArgsSizes<Args...>::type; | |
+ | |
// 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> | |
struct TypeToMoveOp { | |
static constexpr MoveOp::Type value = MoveOp::GENERAL; | |
}; | |
template <> | |
@@ -266,159 +284,166 @@ template <> | |
struct TypeToMoveOp<double> { | |
static constexpr MoveOp::Type value = MoveOp::DOUBLE; | |
}; | |
// Generate an std::integer_sequence which contains the associated MoveOp of | |
// each argument. | |
template <typename... Args> | |
struct ArgsMoveOps { | |
- using Res = std::integer_sequence<MoveOp::Type, TypeToMoveOp<Args>::value...>; | |
+ using type = | |
+ std::integer_sequence<MoveOp::Type, TypeToMoveOp<Args>::value...>; | |
}; | |
+template <typename... Args> | |
+using ArgsMoveOps_t = typename ArgsMoveOps<Args...>::type; | |
+ | |
// 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 GenArgsBuffer; | |
template <uint8_t... Buffer, typename Arg, typename... Args, size_t Val, | |
size_t... Values> | |
struct GenArgsBuffer<std::integer_sequence<uint8_t, Buffer...>, | |
std::integer_sequence<size_t, Val, Values...>, Arg, | |
Args...> { | |
- using Res = typename GenArgsBuffer< | |
- typename Concat< | |
+ using type = typename GenArgsBuffer< | |
+ Concat_t< | |
std::integer_sequence<uint8_t, Buffer...>, | |
- typename Concat< | |
- typename PadSeq<alignof(Arg), sizeof...(Buffer)>::Res, | |
- typename FillSeq<AT_LEAST_SIZE(sizeof(WrapForSizeOf<Arg>)), | |
- Val>::Res>::Res>::Res, | |
- std::integer_sequence<size_t, Values...>, Args...>::Res; | |
+ Concat_t<PadSeq_t<alignof(Arg), sizeof...(Buffer)>, | |
+ typename FillSeq<AT_LEAST_SIZE(sizeof(WrapForSizeOf<Arg>)), | |
+ Val>::type>>, | |
+ std::integer_sequence<size_t, Values...>, Args...>::type; | |
}; | |
template <typename Buffer> | |
struct GenArgsBuffer<Buffer, std::integer_sequence<size_t>> { | |
- using Res = Buffer; | |
+ using type = Buffer; | |
}; | |
template <typename Values, typename... Args> | |
using ArgsBuffer = | |
GenArgsBuffer<std::integer_sequence<uint8_t>, Values, Args...>; | |
// NOTE: The representation of the boolean might be surpising in this test case, | |
// see AT_LEAST_SIZE macro for an explanation. | |
-static_assert(std::is_same<typename ArgsBuffer<std::integer_sequence<size_t, 42, 51>, | |
- uint64_t, bool>::Res, | |
- std::integer_sequence<uint8_t, 42, 0, 0, 0, 0, 0, 0, 0, | |
- 51, 0, 0, 0, 0, 0, 0, 0>>::value); | |
+static_assert( | |
+ std::is_same_v<typename ArgsBuffer<std::integer_sequence<size_t, 42, 51>, | |
+ uint64_t, bool>::type, | |
+ std::integer_sequence<uint8_t, 42, 0, 0, 0, 0, 0, 0, 0, 51, | |
+ 0, 0, 0, 0, 0, 0, 0>>); | |
// Test used to check if any of the type given as template parameter is a | |
// `bool`, which is a corner case where a raw integer might be truncated by the | |
// C++ compiler. | |
template <typename... Args> | |
struct AnyBool; | |
template <> | |
struct AnyBool<> { | |
static constexpr bool value = false; | |
}; | |
template <typename A0, typename... Args> | |
struct AnyBool<A0, Args...> { | |
static constexpr bool value = | |
- std::is_same<A0, bool>::value || AnyBool<Args...>::value; | |
+ std::is_same_v<A0, bool> || AnyBool<Args...>::value; | |
}; | |
+template <typename... Args> | |
+static constexpr bool AnyBool_v = AnyBool<Args...>::value; | |
+ | |
// Instanciate an std::integer_sequence as a buffer which is readable and | |
// addressable at runtime, which is used 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); | |
}; | |
// Instanciate a buffer which is used for testing the position of arguments when | |
// calling a function. | |
template <typename... Args> | |
using TestArgsPositions = InstanceSeq< | |
- typename ArgsBuffer<typename ArgsIndexes<Args...>::Res, Args...>::Res>; | |
+ typename ArgsBuffer<typename ArgsIndexes<Args...>::type, Args...>::type>; | |
// Instanciate a buffer which is used for testing the position of arguments, one | |
// bit at a time, when calling a function. | |
template <size_t Bit, typename... Args> | |
-using TestArgsBitOfPositions = InstanceSeq< | |
- typename ArgsBuffer<typename ArgsBitOfIndexes<Bit, Args...>::Res, Args...>::Res>; | |
+using TestArgsBitOfPositions = InstanceSeq<typename ArgsBuffer< | |
+ typename ArgsBitOfIndexes<Bit, Args...>::type, Args...>::type>; | |
// Instanciate a buffer which is used to check that the size of each argument is | |
// interpreted correctly when calling a function. | |
template <typename... Args> | |
-using TestArgsSizes = InstanceSeq< | |
- typename ArgsBuffer<typename ArgsSizes<Args...>::Res, Args...>::Res>; | |
+using TestArgsSizes = | |
+ InstanceSeq<typename ArgsBuffer<ArgsSizes_t<Args...>, Args...>::type>; | |
// AsInt returns the raw value of any argument as an integer value which can be | |
// compared with the expected values. | |
template <typename Type> | |
struct AsInt { | |
- static typename IntTypeOf<Type>::Res Convert(Type v) { | |
+ static IntTypeOf_t<Type> Convert(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(sizeof(WrapForSizeOf<Type>) == | |
- sizeof(WrapForSizeOf<typename IntTypeOf<Type>::Res>)); | |
- return *reinterpret_cast<const typename IntTypeOf<Type>::Res*>(address); | |
+ sizeof(WrapForSizeOf<IntTypeOf_t<Type>>)); | |
+ return *reinterpret_cast<const IntTypeOf_t<Type>*>(address); | |
} | |
}; | |
template <typename T> | |
struct AsInt<T&> { | |
using Type = T&; | |
- static typename IntTypeOf<Type>::Res Convert(Type v) { | |
+ static IntTypeOf_t<Type> Convert(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(sizeof(WrapForSizeOf<Type>) == | |
- sizeof(WrapForSizeOf<typename IntTypeOf<Type>::Res>)); | |
- return reinterpret_cast<const typename IntTypeOf<Type>::Res>(address); | |
+ sizeof(WrapForSizeOf<IntTypeOf_t<Type>>)); | |
+ return reinterpret_cast<const IntTypeOf_t<Type>>(address); | |
} | |
}; | |
template <typename Type> | |
-typename IntTypeOf<Type>::Res ConvertToInt(Type v) { | |
+IntTypeOf_t<Type> ConvertToInt(Type v) { | |
return AsInt<Type>::Convert(std::forward<Type>(v)); | |
} | |
// Check if the raw value of arguments are equals to the numbers given in the | |
// std::integer_sequence given as the first argument. | |
template <typename Int> | |
bool CheckArgsEqual(std::integer_sequence<Int>) { | |
return true; | |
} | |
template <typename Arg0, typename Int, Int V0> | |
bool CheckArgsEqual(std::integer_sequence<Int, V0>, Arg0 a0) { | |
- using CompareInt = typename IntTypeOf<Arg0>::Res; | |
+ using CompareInt = IntTypeOf_t<Arg0>; | |
if (ConvertToInt<Arg0>(a0) != CompareInt(V0)) { | |
return false; | |
} | |
return true; | |
} | |
template <typename Arg0, typename... Args, typename Int, Int V0, Int... Val> | |
bool CheckArgsEqual(std::integer_sequence<Int, V0, Val...>, Arg0 a0, | |
Args... args) { | |
- using CompareInt = typename IntTypeOf<Arg0>::Res; | |
+ using CompareInt = IntTypeOf_t<Arg0>; | |
if (ConvertToInt<Arg0>(a0) != CompareInt(V0)) { | |
return false; | |
} | |
return CheckArgsEqual<Args...>(std::integer_sequence<Int, Val...>(), | |
std::forward<Args>(args)...); | |
} | |
// Generate code which will register the value of each argument of the called | |
@@ -448,63 +473,63 @@ struct DefineCheckArgs<Res (*)(Args...)> | |
instance_ = instance; | |
} | |
virtual void check_result(bool) = 0; | |
// Check that arguments are interpreted in the same order at compile time and | |
// at runtime. | |
static Res CheckArgsPositions(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsIndexes<Args...>::Res; | |
+ using Indexes = typename ArgsIndexes<Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
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 CheckArgsPositions0(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsBitOfIndexes<0, Args...>::Res; | |
+ using Indexes = typename ArgsBitOfIndexes<0, Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
static Res CheckArgsPositions1(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsBitOfIndexes<1, Args...>::Res; | |
+ using Indexes = typename ArgsBitOfIndexes<1, Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
static Res CheckArgsPositions2(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsBitOfIndexes<2, Args...>::Res; | |
+ using Indexes = typename ArgsBitOfIndexes<2, Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
static Res CheckArgsPositions3(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsBitOfIndexes<3, Args...>::Res; | |
+ using Indexes = typename ArgsBitOfIndexes<3, Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
// Check that the size of each argument, known at compile time and at runtime | |
// are identical. | |
static Res CheckArgsSizes(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Sizes = typename ArgsSizes<Args...>::Res; | |
+ using Sizes = ArgsSizes_t<Args...>; | |
bool res = CheckArgsEqual<Args...>(Sizes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
using FunType = Res (*)(Args...); | |
struct Test { | |
const uint8_t* buffer; | |
@@ -530,28 +555,28 @@ struct DefineCheckArgs<Res (*)(Args...)> | |
{ArgsPositions0::table, ArgsPositions0::size, CheckArgsPositions0}, | |
{ArgsPositions1::table, ArgsPositions1::size, CheckArgsPositions1}, | |
{ArgsPositions2::table, ArgsPositions2::size, CheckArgsPositions2}, | |
{ArgsPositions3::table, ArgsPositions3::size, CheckArgsPositions3}, | |
{ArgsSizes::table, ArgsSizes::size, CheckArgsSizes}, | |
}; | |
const Test* tests = testsWithoutBoolArgs; | |
size_t numTests = 2; | |
- if (AnyBool<Args...>::value) { | |
+ if (AnyBool_v<Args...>) { | |
tests = testsWithBoolArgs; | |
numTests = 5; | |
} | |
for (size_t i = 0; i < numTests; i++) { | |
const Test& test = tests[i]; | |
masm.movePtr(ImmPtr(test.buffer), base); | |
masm.setupUnalignedABICall(setup); | |
- using Offsets = typename ArgsOffsets<0, Args...>::Res; | |
- using MoveOps = typename ArgsMoveOps<Args...>::Res; | |
+ 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)}, | |
MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther); | |
} | |
} | |
private: | |
// As we are checking specific function signature, we cannot add extra | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601596630 25200 | |
# Thu Oct 01 16:57:10 2020 -0700 | |
# Node ID 4383fff479c17a6e831cf098eb8e7c3ce7a54028 | |
# Parent cee51d93f57a7cd37195a357d7c17bb0cd9e16fc | |
Allow JSAPI tests to opt-in to reuse a global and cx instead of tearing everything down and starting up every time. | |
Cons: (1) messy, (2) may be unnecessary once Stencil allows better caching of self-hosted code. | |
Pros: 322x faster for testJitABIcalls. | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -634,17 +634,17 @@ static bool Execute(JSContext* cx, Macro | |
// initialized with the name of the function which has 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 : public JSAPITest, public DefineCheckArgs<Sig> { | |
public: | |
- JitABICall(const char* name) : name_(name) {} | |
+ JitABICall(const char* name) : name_(name) { reuseGlobal = true; } | |
virtual void check_result(bool res) override { | |
result_ = result_ && check_result_wrapped(res); | |
} | |
virtual const char* name() override { return name_; } | |
virtual bool run(JS::HandleObject) override { | |
this->set_instance(this); | |
result_ = true; | |
@@ -676,17 +676,17 @@ class JitABICall : public JSAPITest, pub | |
template <typename Sig> | |
bool JitABICall<Sig>::result_ = false; | |
// 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)(Name); | |
+ _instance)("JITABI " 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__)) | |
diff --git a/js/src/jsapi-tests/tests.cpp b/js/src/jsapi-tests/tests.cpp | |
--- a/js/src/jsapi-tests/tests.cpp | |
+++ b/js/src/jsapi-tests/tests.cpp | |
@@ -12,16 +12,25 @@ | |
#include "js/CompilationAndEvaluation.h" // JS::Evaluate | |
#include "js/Initialization.h" | |
#include "js/RootingAPI.h" | |
#include "js/SourceText.h" // JS::Source{Ownership,Text} | |
JSAPITest* JSAPITest::list; | |
+bool JSAPITest::init(JSContext* reused_cx) { | |
+ if (reused_cx) { | |
+ cx = reused_cx; | |
+ global.init(cx, cx->global()); | |
+ return true; | |
+ } | |
+ return init(); | |
+} | |
+ | |
bool JSAPITest::init() { | |
cx = createContext(); | |
if (!cx) { | |
return false; | |
} | |
js::UseInternalJobQueues(cx); | |
if (!JS::InitSelfHostedCode(cx)) { | |
return false; | |
@@ -30,26 +39,27 @@ bool JSAPITest::init() { | |
createGlobal(); | |
if (!global) { | |
return false; | |
} | |
JS::EnterRealm(cx, global); | |
return true; | |
} | |
+void JSAPITest::finish() { msgs.clear(); } | |
+ | |
void JSAPITest::uninit() { | |
if (global) { | |
JS::LeaveRealm(cx, nullptr); | |
global = nullptr; | |
} | |
if (cx) { | |
destroyContext(); | |
cx = nullptr; | |
} | |
- msgs.clear(); | |
} | |
bool JSAPITest::exec(const char* utf8, const char* filename, int lineno) { | |
JS::CompileOptions opts(cx); | |
opts.setFileAndLine(filename, lineno); | |
JS::SourceText<mozilla::Utf8Unit> srcBuf; | |
JS::RootedValue v(cx); | |
@@ -107,26 +117,48 @@ int main(int argc, char* argv[]) { | |
int failures = 0; | |
const char* filter = (argc == 2) ? argv[1] : nullptr; | |
if (!JS_Init()) { | |
printf("TEST-UNEXPECTED-FAIL | jsapi-tests | JS_Init() failed.\n"); | |
return 1; | |
} | |
+ if (strcmp(filter, "--list") == 0) { | |
+ for (JSAPITest* test = JSAPITest::list; test; test = test->next) { | |
+ printf("%s\n", test->name()); | |
+ } | |
+ return 0; | |
+ } | |
+ | |
+ // Reinitializing the global for every test is quite slow, due to having to | |
+ // recompile all self-hosted builtins. Allow tests to opt-in to reusing the | |
+ // global. | |
+ JSAPITest* reusableTest = nullptr; | |
+ | |
for (JSAPITest* test = JSAPITest::list; test; test = test->next) { | |
const char* name = test->name(); | |
if (filter && strstr(name, filter) == nullptr) { | |
continue; | |
} | |
total += 1; | |
printf("%s\n", name); | |
- if (!test->init()) { | |
+ JSContext* reusedContext = nullptr; | |
+ if (reusableTest) { | |
+ if (test->reuseGlobal) { | |
+ reusedContext = reusableTest->releaseContext(); | |
+ } else { | |
+ reusableTest->uninit(); | |
+ } | |
+ reusableTest = nullptr; | |
+ } | |
+ | |
+ if (!test->init(reusedContext)) { | |
printf("TEST-UNEXPECTED-FAIL | %s | Failed to initialize.\n", name); | |
failures++; | |
test->uninit(); | |
continue; | |
} | |
if (test->run(test->global)) { | |
printf("TEST-PASS | %s | ok\n", name); | |
@@ -134,17 +166,26 @@ int main(int argc, char* argv[]) { | |
JSAPITestString messages = test->messages(); | |
printf("%s | %s | %.*s\n", | |
(test->knownFail ? "TEST-KNOWN-FAIL" : "TEST-UNEXPECTED-FAIL"), | |
name, (int)messages.length(), messages.begin()); | |
if (!test->knownFail) { | |
failures++; | |
} | |
} | |
- test->uninit(); | |
+ | |
+ test->finish(); | |
+ if (test->reuseGlobal) { | |
+ reusableTest = test; | |
+ } else { | |
+ test->uninit(); | |
+ } | |
+ } | |
+ if (reusableTest) { | |
+ reusableTest->uninit(); | |
} | |
MOZ_RELEASE_ASSERT(!JSRuntime::hasLiveRuntimes()); | |
JS_ShutDown(); | |
if (failures) { | |
printf("\n%d unexpected failure%s.\n", failures, | |
(failures == 1 ? "" : "s")); | |
diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h | |
--- a/js/src/jsapi-tests/tests.h | |
+++ b/js/src/jsapi-tests/tests.h | |
@@ -72,27 +72,45 @@ class JSAPITest { | |
static JSAPITest* list; | |
JSAPITest* next; | |
JSContext* cx; | |
JS::PersistentRootedObject global; | |
bool knownFail; | |
JSAPITestString msgs; | |
+ // Whether this test is willing to skip its init() and reuse a global (and | |
+ // JSContext etc.) from a previous test that also has reuseGlobal=true. It | |
+ // also means this test is willing to skip its uninit() if it is followed by | |
+ // another reuseGlobal test. | |
+ bool reuseGlobal; | |
+ | |
JSAPITest() : cx(nullptr), knownFail(false) { | |
next = list; | |
list = this; | |
+ reuseGlobal = false; | |
} | |
virtual ~JSAPITest() { | |
MOZ_RELEASE_ASSERT(!cx); | |
MOZ_RELEASE_ASSERT(!global); | |
} | |
+ // Initialize this test, possibly with the cx from a previously run test. | |
+ bool init(JSContext* reused_cx); | |
+ | |
+ // Release this test's cx to be reused by another test. | |
+ JSContext* releaseContext() { | |
+ JSContext* ret = cx; | |
+ cx = nullptr; | |
+ return ret; | |
+ } | |
+ | |
virtual bool init(); | |
+ virtual void finish(); | |
virtual void uninit(); | |
virtual const char* name() = 0; | |
virtual bool run(JS::HandleObject global) = 0; | |
#define EXEC(s) \ | |
do { \ | |
if (!exec(s, __FILE__, __LINE__)) return false; \ | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601658360 25200 | |
# Fri Oct 02 10:06:00 2020 -0700 | |
# Node ID cbc6bc542e7028b8ca97b9b4f24cc4f169ac36b8 | |
# Parent 4383fff479c17a6e831cf098eb8e7c3ce7a54028 | |
Just an option -- instead of WrapForSizeOf, which is clever but a little indirect -- make an AsParameter<T> | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -81,31 +81,30 @@ struct IntBySize<4> { | |
using type = uint32_t; | |
}; | |
template <> | |
struct IntBySize<8> { | |
using type = uint64_t; | |
}; | |
-// sizeof(const T&) is not equal to sizeof(const T*). This structure is used to | |
-// wrap the type which size is being queried, instead of the size of the type | |
-// referenced by it. | |
+// 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) | |
template <typename T> | |
-struct WrapForSizeOf { | |
- T unused_; | |
-}; | |
+using AsParameter = | |
+ typename std::conditional<std::is_reference_v<T>, | |
+ std::remove_reference_t<T>*, T>::type; | |
// Given a type, return the integer type which has the same size. | |
template <typename T> | |
struct IntTypeOf { | |
- using type = typename IntBySize<sizeof(WrapForSizeOf<T>)>::type; | |
+ using type = typename IntBySize<sizeof(AsParameter<T>)>::type; | |
}; | |
template <typename T> | |
using IntTypeOf_t = typename IntTypeOf<T>::type; | |
// Concatenate 2 std::integer_sequence, and return an std::integer_sequence with | |
// the content of both parameters. | |
template <typename Before, typename After> | |
@@ -156,19 +155,19 @@ using CstSeq_t = typename CstSeq<N, Valu | |
// | |
// This macro ensure that the MoveOperand would read the zero-ed padding added | |
// in front of the each value, if it reads too much. | |
#define AT_LEAST_SIZE(SIZE) \ | |
((SIZE) < sizeof(uintptr_t) ? sizeof(uintptr_t) : (SIZE)) | |
// Adds the padding and the reserved size for storing a value in a buffer which | |
// can be read by a MoveOperand. | |
-#define PADSIZE(SIZE, TYPE) \ | |
- PADDING(Size, alignof(WrapForSizeOf<TYPE>)) + \ | |
- AT_LEAST_SIZE(sizeof(WrapForSizeOf<TYPE>)) | |
+#define PADSIZE(SIZE, TYPE) \ | |
+ PADDING(Size, alignof(AsParameter<TYPE>)) + \ | |
+ AT_LEAST_SIZE(sizeof(AsParameter<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 = CstSeq<PADDING(CurrSize, Align), 0>; | |
template <size_t Align, size_t CurrSize> | |
using PadSeq_t = typename PadSeq<Align, CurrSize>::type; | |
@@ -257,17 +256,17 @@ using ArgsOffsets_t = typename ArgsOffse | |
static_assert(std::is_same_v<ArgsOffsets_t<0, uint8_t, uint64_t, bool>, | |
std::integer_sequence<size_t, 0, 8, 16>>); | |
// Generate an std::integer_sequence containing the size of each argument in | |
// memory. | |
template <typename... Args> | |
struct ArgsSizes { | |
- using type = std::integer_sequence<size_t, sizeof(WrapForSizeOf<Args>)...>; | |
+ using type = std::integer_sequence<size_t, sizeof(AsParameter<Args>)...>; | |
}; | |
template <typename... Args> | |
using ArgsSizes_t = typename ArgsSizes<Args...>::type; | |
// 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> | |
@@ -306,17 +305,17 @@ template <uint8_t... Buffer, typename Ar | |
size_t... Values> | |
struct GenArgsBuffer<std::integer_sequence<uint8_t, Buffer...>, | |
std::integer_sequence<size_t, Val, Values...>, Arg, | |
Args...> { | |
using type = typename GenArgsBuffer< | |
Concat_t< | |
std::integer_sequence<uint8_t, Buffer...>, | |
Concat_t<PadSeq_t<alignof(Arg), sizeof...(Buffer)>, | |
- typename FillSeq<AT_LEAST_SIZE(sizeof(WrapForSizeOf<Arg>)), | |
+ typename FillSeq<AT_LEAST_SIZE(sizeof(AsParameter<Arg>)), | |
Val>::type>>, | |
std::integer_sequence<size_t, Values...>, Args...>::type; | |
}; | |
template <typename Buffer> | |
struct GenArgsBuffer<Buffer, std::integer_sequence<size_t>> { | |
using type = Buffer; | |
}; | |
@@ -388,33 +387,33 @@ using TestArgsSizes = | |
template <typename Type> | |
struct AsInt { | |
static IntTypeOf_t<Type> Convert(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(sizeof(WrapForSizeOf<Type>) == | |
- sizeof(WrapForSizeOf<IntTypeOf_t<Type>>)); | |
+ static_assert(sizeof(AsParameter<Type>) == | |
+ sizeof(AsParameter<IntTypeOf_t<Type>>)); | |
return *reinterpret_cast<const IntTypeOf_t<Type>*>(address); | |
} | |
}; | |
template <typename T> | |
struct AsInt<T&> { | |
using Type = T&; | |
static IntTypeOf_t<Type> Convert(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(sizeof(WrapForSizeOf<Type>) == | |
- sizeof(WrapForSizeOf<IntTypeOf_t<Type>>)); | |
+ static_assert(sizeof(AsParameter<Type>) == | |
+ sizeof(AsParameter<IntTypeOf_t<Type>>)); | |
return reinterpret_cast<const IntTypeOf_t<Type>>(address); | |
} | |
}; | |
template <typename Type> | |
IntTypeOf_t<Type> ConvertToInt(Type v) { | |
return AsInt<Type>::Convert(std::forward<Type>(v)); | |
} | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601658624 25200 | |
# Fri Oct 02 10:10:24 2020 -0700 | |
# Node ID 42d2e88d3714ba846ed83f5e0b2b235b7dc83944 | |
# Parent cbc6bc542e7028b8ca97b9b4f24cc4f169ac36b8 | |
Remove some code with `if constexpr` | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -389,32 +389,21 @@ struct AsInt { | |
static IntTypeOf_t<Type> Convert(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(sizeof(AsParameter<Type>) == | |
sizeof(AsParameter<IntTypeOf_t<Type>>)); | |
- return *reinterpret_cast<const IntTypeOf_t<Type>*>(address); | |
- } | |
-}; | |
- | |
-template <typename T> | |
-struct AsInt<T&> { | |
- using Type = T&; | |
- static IntTypeOf_t<Type> Convert(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(sizeof(AsParameter<Type>) == | |
- sizeof(AsParameter<IntTypeOf_t<Type>>)); | |
- return reinterpret_cast<const IntTypeOf_t<Type>>(address); | |
+ if constexpr (std::is_reference_v<Type>) { | |
+ return reinterpret_cast<const IntTypeOf_t<Type>>(address); | |
+ } else { | |
+ return *reinterpret_cast<const IntTypeOf_t<Type>*>(address); | |
+ } | |
} | |
}; | |
template <typename Type> | |
IntTypeOf_t<Type> ConvertToInt(Type v) { | |
return AsInt<Type>::Convert(std::forward<Type>(v)); | |
} | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601670279 25200 | |
# Fri Oct 02 13:24:39 2020 -0700 | |
# Node ID 05246ab2d673393e4f37bc4db5b6df91ab3bf62f | |
# Parent 42d2e88d3714ba846ed83f5e0b2b235b7dc83944 | |
Not sure about this one, but it seemed odd to have a new name for std::index_sequence_for. Then again, giving it a new name makes it look more like the other similar sequences. | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -194,42 +194,31 @@ struct FillLESeq<0, Value, Rest...> { | |
}; | |
template <size_t N, size_t Value> | |
using FillSeq = FillLESeq<N, Value>; | |
static_assert(std::is_same_v<typename FillSeq<4, 2>::type, | |
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> | |
-struct ArgsIndexes { | |
- using type = std::index_sequence_for<Args...>; | |
-}; | |
- | |
-static_assert(std::is_same_v<typename ArgsIndexes<uint8_t, uint64_t>::type, | |
- std::integer_sequence<size_t, 0, 1>>); | |
- | |
// Extract a single bit for each element of an std::integer_sequence. This is | |
// used to work-around some restriction around providing boolean arguments, | |
// which might be truncated to a single bit. | |
template <size_t Bit, typename IntSeq> | |
struct ExtractBit; | |
template <size_t Bit, size_t... Values> | |
struct ExtractBit<Bit, std::integer_sequence<size_t, Values...>> { | |
using type = std::integer_sequence<size_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 = ExtractBit<Bit, typename ArgsIndexes<Args...>::type>; | |
+using ArgsBitOfIndexes = ExtractBit<Bit, std::index_sequence_for<Args...>>; | |
static_assert( | |
std::is_same_v<typename ArgsBitOfIndexes<0, int, int, int, int>::type, | |
std::integer_sequence<size_t, 0, 1, 0, 1>>); | |
static_assert( | |
std::is_same_v<typename ArgsBitOfIndexes<1, int, int, int, int>::type, | |
std::integer_sequence<size_t, 0, 0, 1, 1>>); | |
@@ -363,17 +352,17 @@ struct InstanceSeq<std::integer_sequence | |
static constexpr Int table[sizeof...(Values)] = {Values...}; | |
static constexpr size_t size = sizeof...(Values); | |
}; | |
// Instanciate a buffer which is used for testing the position of arguments when | |
// calling a function. | |
template <typename... Args> | |
using TestArgsPositions = InstanceSeq< | |
- typename ArgsBuffer<typename ArgsIndexes<Args...>::type, Args...>::type>; | |
+ typename ArgsBuffer<std::index_sequence_for<Args...>, Args...>::type>; | |
// Instanciate a buffer which is used for testing the position of arguments, one | |
// bit at a time, when calling a function. | |
template <size_t Bit, typename... Args> | |
using TestArgsBitOfPositions = InstanceSeq<typename ArgsBuffer< | |
typename ArgsBitOfIndexes<Bit, Args...>::type, Args...>::type>; | |
// Instanciate a buffer which is used to check that the size of each argument is | |
@@ -461,17 +450,17 @@ struct DefineCheckArgs<Res (*)(Args...)> | |
instance_ = instance; | |
} | |
virtual void check_result(bool) = 0; | |
// Check that arguments are interpreted in the same order at compile time and | |
// at runtime. | |
static Res CheckArgsPositions(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
- using Indexes = typename ArgsIndexes<Args...>::type; | |
+ using Indexes = std::index_sequence_for<Args...>; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
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 | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601670393 25200 | |
# Fri Oct 02 13:26:33 2020 -0700 | |
# Node ID 55ad64aeac201e237f8d7261d86d4ae74de8c6a1 | |
# Parent 05246ab2d673393e4f37bc4db5b6df91ab3bf62f | |
Small tweaks | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -141,38 +141,37 @@ struct CstSeq<1, Value> { | |
using type = std::integer_sequence<uint8_t, Value>; | |
}; | |
template <size_t N, uint8_t Value> | |
using CstSeq_t = typename CstSeq<N, Value>::type; | |
// Computes the number of bytes to add before a type in order to align it in | |
// memory. | |
-#define PADDING(SIZE, ALIGN) ((ALIGN) - ((SIZE) % (ALIGN))) % (ALIGN) | |
+#define PADBYTES(SIZE, ALIGN) ((ALIGN) - ((SIZE) % (ALIGN))) % (ALIGN) | |
// Request a minimum alignment for the values which are added in a buffer, in | |
// order to account for the read size used by the MoveOperand given as argument | |
// of passWithABI. The MoveOperand do not take into consideration the size of | |
// the data which is being transfered, and might load a larger amount of data. | |
// | |
// This macro ensure that the MoveOperand would read the zero-ed padding added | |
// in front of the each value, if it reads too much. | |
-#define AT_LEAST_SIZE(SIZE) \ | |
- ((SIZE) < sizeof(uintptr_t) ? sizeof(uintptr_t) : (SIZE)) | |
+#define AT_LEAST_SIZE(SIZE) std::max((SIZE), sizeof(uintptr_t)) | |
// Adds the padding and the reserved size for storing a value in a buffer which | |
// can be read by a MoveOperand. | |
#define PADSIZE(SIZE, TYPE) \ | |
- PADDING(Size, alignof(AsParameter<TYPE>)) + \ | |
+ PADBYTES(Size, alignof(AsParameter<TYPE>)) + \ | |
AT_LEAST_SIZE(sizeof(AsParameter<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 = CstSeq<PADDING(CurrSize, Align), 0>; | |
+using PadSeq = CstSeq<PADBYTES(CurrSize, Align), 0>; | |
template <size_t Align, size_t CurrSize> | |
using PadSeq_t = typename PadSeq<Align, CurrSize>::type; | |
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( | |
@@ -231,17 +230,17 @@ struct ArgsOffsets; | |
template <size_t Size> | |
struct ArgsOffsets<Size> { | |
using type = std::integer_sequence<size_t>; | |
}; | |
template <size_t Size, typename Arg, typename... Args> | |
struct ArgsOffsets<Size, Arg, Args...> { | |
using type = Concat_t< | |
- std::integer_sequence<size_t, Size + PADDING(Size, alignof(Arg))>, | |
+ std::integer_sequence<size_t, Size + PADBYTES(Size, alignof(Arg))>, | |
typename ArgsOffsets<Size + PADSIZE(Size, Arg), Args...>::type>; | |
}; | |
template <size_t Size, typename... Args> | |
using ArgsOffsets_t = typename ArgsOffsets<Size, Args...>::type; | |
static_assert(std::is_same_v<ArgsOffsets_t<0, uint8_t, uint64_t, bool>, | |
std::integer_sequence<size_t, 0, 8, 16>>); | |
# HG changeset patch | |
# User Steve Fink <[email protected]> | |
# Date 1601658665 25200 | |
# Fri Oct 02 10:11:05 2020 -0700 | |
# Node ID 34cad7f28fc64af7e00f0e6620551a002f208877 | |
# Parent 55ad64aeac201e237f8d7261d86d4ae74de8c6a1 | |
Comment fixups | |
diff --git a/js/src/jsapi-tests/testJitABIcalls.cpp b/js/src/jsapi-tests/testJitABIcalls.cpp | |
--- a/js/src/jsapi-tests/testJitABIcalls.cpp | |
+++ b/js/src/jsapi-tests/testJitABIcalls.cpp | |
@@ -27,38 +27,38 @@ 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 check 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-interpret the arguments content to ensure that it matches the content | |
-// given as argument by the JIT. | |
+// 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 imply that either the | |
-// MacroAssembler are not used properly, or that the code used by the JIT to | |
-// generate the function call does not match the ABI of the targetted system. | |
+// 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 diffferent macro call based on the type of the | |
+// 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) | |
@@ -119,17 +119,17 @@ struct Concat<std::integer_sequence<Int, | |
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 integers with value `Value`. | |
+// uint8_t integer with value `Value`. | |
template <size_t N, uint8_t Value> | |
struct CstSeq { | |
using type = Concat_t<typename CstSeq<N / 2, Value>::type, | |
typename CstSeq<N - N / 2, Value>::type>; | |
}; | |
template <uint8_t Value> | |
struct CstSeq<0, Value> { | |
@@ -143,32 +143,32 @@ struct CstSeq<1, Value> { | |
template <size_t N, uint8_t Value> | |
using CstSeq_t = typename CstSeq<N, Value>::type; | |
// Computes the number of bytes to add before a type in order to align it in | |
// memory. | |
#define PADBYTES(SIZE, ALIGN) ((ALIGN) - ((SIZE) % (ALIGN))) % (ALIGN) | |
-// Request a minimum alignment for the values which are added in a buffer, in | |
-// order to account for the read size used by the MoveOperand given as argument | |
-// of passWithABI. The MoveOperand do not take into consideration the size of | |
-// the data which is being transfered, and might load a larger amount of data. | |
+// 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 macro ensure that the MoveOperand would read the zero-ed padding added | |
+// This macro ensures that the MoveOperand would read the zero-ed padding added | |
// in front of the each value, if it reads too much. | |
#define AT_LEAST_SIZE(SIZE) std::max((SIZE), sizeof(uintptr_t)) | |
// Adds the padding and the reserved size for storing a value in a buffer which | |
// can be read by a MoveOperand. | |
#define PADSIZE(SIZE, TYPE) \ | |
PADBYTES(Size, alignof(AsParameter<TYPE>)) + \ | |
AT_LEAST_SIZE(sizeof(AsParameter<TYPE>)) | |
-// Generate an std::integer_sequence of 0 uint8_t elements of the size of the | |
+// 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 = CstSeq<PADBYTES(CurrSize, Align), 0>; | |
template <size_t Align, size_t CurrSize> | |
using PadSeq_t = typename PadSeq<Align, CurrSize>::type; | |
static_assert(std::is_same_v<PadSeq_t<4, 0>, std::integer_sequence<uint8_t>>); | |
@@ -194,17 +194,17 @@ struct FillLESeq<0, Value, Rest...> { | |
template <size_t N, size_t Value> | |
using FillSeq = FillLESeq<N, Value>; | |
static_assert(std::is_same_v<typename FillSeq<4, 2>::type, | |
std::integer_sequence<uint8_t, 2, 0, 0, 0>>); | |
// Extract a single bit for each element of an std::integer_sequence. This is | |
-// used to work-around some restriction around providing boolean arguments, | |
+// 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, size_t... Values> | |
struct ExtractBit<Bit, std::integer_sequence<size_t, Values...>> { | |
using type = std::integer_sequence<size_t, (Values >> Bit) & 1 ...>; | |
}; | |
@@ -307,25 +307,25 @@ template <typename Buffer> | |
struct GenArgsBuffer<Buffer, std::integer_sequence<size_t>> { | |
using type = Buffer; | |
}; | |
template <typename Values, typename... Args> | |
using ArgsBuffer = | |
GenArgsBuffer<std::integer_sequence<uint8_t>, Values, Args...>; | |
-// NOTE: The representation of the boolean might be surpising in this test case, | |
-// see AT_LEAST_SIZE macro for an explanation. | |
+// NOTE: The representation of the boolean might be surprising in this test | |
+// case, see AT_LEAST_SIZE macro for an explanation. | |
static_assert( | |
std::is_same_v<typename ArgsBuffer<std::integer_sequence<size_t, 42, 51>, | |
uint64_t, bool>::type, | |
std::integer_sequence<uint8_t, 42, 0, 0, 0, 0, 0, 0, 0, 51, | |
0, 0, 0, 0, 0, 0, 0>>); | |
-// Test used to check if any of the type given as template parameter is a | |
+// Test used to check if any of the types given as template parameters are | |
// `bool`, which is a corner case where a raw integer might be truncated by the | |
// C++ compiler. | |
template <typename... Args> | |
struct AnyBool; | |
template <> | |
struct AnyBool<> { | |
static constexpr bool value = false; | |
@@ -335,42 +335,41 @@ template <typename A0, typename... Args> | |
struct AnyBool<A0, Args...> { | |
static constexpr bool value = | |
std::is_same_v<A0, bool> || AnyBool<Args...>::value; | |
}; | |
template <typename... Args> | |
static constexpr bool AnyBool_v = AnyBool<Args...>::value; | |
-// Instanciate an std::integer_sequence as a buffer which is readable and | |
-// addressable at runtime, which is used for reading argument values from the | |
-// generated code. | |
+// 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); | |
}; | |
-// Instanciate a buffer which is used for testing the position of arguments when | |
-// calling a function. | |
+// Instantiate a buffer for testing the position of arguments when calling a | |
+// function. | |
template <typename... Args> | |
using TestArgsPositions = InstanceSeq< | |
typename ArgsBuffer<std::index_sequence_for<Args...>, Args...>::type>; | |
-// Instanciate a buffer which is used for testing the position of arguments, one | |
-// bit at a time, when calling a function. | |
+// 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<typename ArgsBuffer< | |
typename ArgsBitOfIndexes<Bit, Args...>::type, Args...>::type>; | |
-// Instanciate a buffer which is used to check that the size of each argument is | |
-// interpreted correctly when calling a function. | |
+// Instantiate a buffer to check that the size of each argument is interpreted | |
+// correctly when calling a function. | |
template <typename... Args> | |
using TestArgsSizes = | |
InstanceSeq<typename ArgsBuffer<ArgsSizes_t<Args...>, Args...>::type>; | |
// AsInt returns the raw value of any argument as an integer value which can be | |
// compared with the expected values. | |
template <typename Type> | |
struct AsInt { | |
@@ -390,17 +389,17 @@ struct AsInt { | |
} | |
}; | |
template <typename Type> | |
IntTypeOf_t<Type> ConvertToInt(Type v) { | |
return AsInt<Type>::Convert(std::forward<Type>(v)); | |
} | |
-// Check if the raw value of arguments are equals to the numbers given in the | |
+// 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 Int> | |
bool CheckArgsEqual(std::integer_sequence<Int>) { | |
return true; | |
} | |
template <typename Arg0, typename Int, Int V0> | |
bool CheckArgsEqual(std::integer_sequence<Int, V0>, Arg0 a0) { | |
@@ -417,33 +416,34 @@ bool CheckArgsEqual(std::integer_sequenc | |
using CompareInt = IntTypeOf_t<Arg0>; | |
if (ConvertToInt<Arg0>(a0) != CompareInt(V0)) { | |
return false; | |
} | |
return CheckArgsEqual<Args...>(std::integer_sequence<Int, Val...>(), | |
std::forward<Args>(args)...); | |
} | |
-// Generate code which will register the value of each argument of the called | |
-// function. Each argument content is read from a buffer which address is stored | |
-// in the `base` register. The offset of arguments as third argument is expected | |
-// to be generated by `ArgsOffsets`. The MoveOp type of arguments as fourth | |
-// argument is expected to be generated by `ArgsMoveOp`. | |
+// 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 <size_t... Off, MoveOp::Type... Move> | |
static void passABIArgs(MacroAssembler& masm, Register base, | |
std::integer_sequence<size_t, Off...>, | |
std::integer_sequence<MoveOp::Type, Move...>) { | |
(masm.passABIArg(MoveOperand(base, Off), Move), ...); | |
} | |
-// For each function type given as parameter, create a few function with the | |
+// 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 would report the result through the `check_result` function and | |
-// rely on the `set_instance` function, as we cannot add extra arguments to | |
-// these functions. | |
+// functions report the result through the `check_result` function and rely on | |
+// 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(DefineCheckArgs* instance) { | |
MOZ_ASSERT((!instance_) != (!instance)); | |
instance_ = instance; | |
@@ -491,36 +491,36 @@ struct DefineCheckArgs<Res (*)(Args...)> | |
static Res CheckArgsPositions3(Args... args) { | |
AutoUnsafeCallWithABI unsafe; | |
using Indexes = typename ArgsBitOfIndexes<3, Args...>::type; | |
bool res = CheckArgsEqual<Args...>(Indexes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
- // Check that the size of each argument, known at compile time and at runtime | |
- // are identical. | |
+ // 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...>; | |
bool res = CheckArgsEqual<Args...>(Sizes(), std::forward<Args>(args)...); | |
instance_->check_result(res); | |
return Res(); | |
} | |
using FunType = Res (*)(Args...); | |
struct Test { | |
const uint8_t* buffer; | |
const size_t size; | |
const FunType fun; | |
}; | |
- // Generate JIT code which is in charge of calling the above test function | |
- // where each argument is given a raw value which would be compared by each | |
- // function called. | |
+ // 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 ArgsPositions0 = TestArgsBitOfPositions<0, Args...>; | |
using ArgsPositions1 = TestArgsBitOfPositions<1, Args...>; | |
using ArgsPositions2 = TestArgsBitOfPositions<2, Args...>; | |
using ArgsPositions3 = TestArgsBitOfPositions<3, Args...>; | |
using ArgsSizes = TestArgsSizes<Args...>; | |
const Test testsWithoutBoolArgs[2] = { | |
@@ -562,17 +562,17 @@ struct DefineCheckArgs<Res (*)(Args...)> | |
}; | |
template <typename Res, typename... Args> | |
DefineCheckArgs<Res (*)(Args...)>* | |
DefineCheckArgs<Res (*)(Args...)>::instance_ = nullptr; | |
typedef void (*EnterTest)(); | |
-// On entry in the JIT code, save every register. | |
+// On entry to the JIT code, save every register. | |
static void Prepare(MacroAssembler& masm) { | |
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. | |
@@ -599,20 +599,20 @@ static bool Execute(JSContext* cx, Macro | |
} | |
JS::AutoSuppressGCAnalysis suppress; | |
EnterTest test = code->as<EnterTest>(); | |
test(); | |
return true; | |
} | |
-// This is an child class of the JSAPITest, which is used behind the scene to | |
+// 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 which has the given signature. | |
+// 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 : public JSAPITest, public DefineCheckArgs<Sig> { | |
public: | |
JitABICall(const char* name) : name_(name) { reuseGlobal = true; } | |
@@ -648,21 +648,21 @@ class JitABICall : public JSAPITest, pub | |
CHECK_EQUAL(res, true); | |
return true; | |
} | |
}; | |
template <typename Sig> | |
bool JitABICall<Sig>::result_ = false; | |
-// For each VMFunction and ABIFunction, create an instance of a JitABICall class | |
-// to register a jsapi-tests test case. | |
+// 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)("JITABI " Name); | |
+ _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__)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment