summaryrefslogtreecommitdiffstats
path: root/js/src/jit/IonTypes.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jit/IonTypes.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit/IonTypes.h')
-rw-r--r--js/src/jit/IonTypes.h875
1 files changed, 875 insertions, 0 deletions
diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h
new file mode 100644
index 000000000..1236e5fe5
--- /dev/null
+++ b/js/src/jit/IonTypes.h
@@ -0,0 +1,875 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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_IonTypes_h
+#define jit_IonTypes_h
+
+#include "mozilla/HashFunctions.h"
+
+#include <algorithm>
+
+#include "jsfriendapi.h"
+#include "jstypes.h"
+
+#include "js/GCAPI.h"
+#include "js/Value.h"
+#include "vm/String.h"
+
+namespace js {
+namespace jit {
+
+typedef uint32_t RecoverOffset;
+typedef uint32_t SnapshotOffset;
+typedef uint32_t BailoutId;
+
+// The maximum size of any buffer associated with an assembler or code object.
+// This is chosen to not overflow a signed integer, leaving room for an extra
+// bit on offsets.
+static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
+
+// Maximum number of scripted arg slots.
+static const uint32_t SNAPSHOT_MAX_NARGS = 127;
+
+static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
+static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
+
+// Different kinds of bailouts. When extending this enum, make sure to check
+// the bits reserved for bailout kinds in Bailouts.h
+enum BailoutKind
+{
+ // Normal bailouts, that don't need to be handled specially when restarting
+ // in baseline.
+
+ // An inevitable bailout (MBail instruction or type barrier that always bails)
+ Bailout_Inevitable,
+
+ // Bailing out during a VM call. Many possible causes that are hard
+ // to distinguish statically at snapshot construction time.
+ // We just lump them together.
+ Bailout_DuringVMCall,
+
+ // Call to a non-JSFunction (problem for |apply|)
+ Bailout_NonJSFunctionCallee,
+
+ // Dynamic scope chain lookup produced |undefined|
+ Bailout_DynamicNameNotFound,
+
+ // Input string contains 'arguments' or 'eval'
+ Bailout_StringArgumentsEval,
+
+ // Bailout on overflow, but don't immediately invalidate.
+ // Used for abs, sub and LoadUnboxedScalar (when loading a uint32 that
+ // doesn't fit in an int32).
+ Bailout_Overflow,
+
+ // floor, ceiling and round bail if input is NaN, if output would be -0 or
+ // doesn't fit in int32 range
+ Bailout_Round,
+
+ // Non-primitive value used as input for ToDouble, ToInt32, ToString, etc.
+ // For ToInt32, can also mean that input can't be converted without precision
+ // loss (e.g. 5.5).
+ Bailout_NonPrimitiveInput,
+
+ // For ToInt32, would lose precision when converting (e.g. 5.5).
+ Bailout_PrecisionLoss,
+
+ // We tripped a type barrier (object was not in the expected TypeSet)
+ Bailout_TypeBarrierO,
+ // We tripped a type barrier (value was not in the expected TypeSet)
+ Bailout_TypeBarrierV,
+ // We tripped a type monitor (wrote an unexpected type in a property)
+ Bailout_MonitorTypes,
+
+ // We hit a hole in an array.
+ Bailout_Hole,
+
+ // Array access with negative index
+ Bailout_NegativeIndex,
+
+ // Pretty specific case:
+ // - need a type barrier on a property write
+ // - all but one of the observed types have property types that reflect the value
+ // - we need to guard that we're not given an object of that one other type
+ // also used for the unused GuardClass instruction
+ Bailout_ObjectIdentityOrTypeGuard,
+
+ // Unbox expects a given type, bails out if it doesn't get it.
+ Bailout_NonInt32Input,
+ Bailout_NonNumericInput, // unboxing a double works with int32 too
+ Bailout_NonBooleanInput,
+ Bailout_NonObjectInput,
+ Bailout_NonStringInput,
+ Bailout_NonSymbolInput,
+
+ // SIMD Unbox expects a given type, bails out if it doesn't match.
+ Bailout_UnexpectedSimdInput,
+
+ // Atomic operations require shared memory, bail out if the typed array
+ // maps unshared memory.
+ Bailout_NonSharedTypedArrayInput,
+
+ // We hit a |debugger;| statement.
+ Bailout_Debugger,
+
+ // |this| used uninitialized in a derived constructor
+ Bailout_UninitializedThis,
+
+ // Derived constructors must return object or undefined
+ Bailout_BadDerivedConstructorReturn,
+
+ // We hit this code for the first time.
+ Bailout_FirstExecution,
+
+ // END Normal bailouts
+
+ // Bailouts caused by invalid assumptions based on Baseline code.
+ // Causes immediate invalidation.
+
+ // Like Bailout_Overflow, but causes immediate invalidation.
+ Bailout_OverflowInvalidate,
+
+ // Like NonStringInput, but should cause immediate invalidation.
+ // Used for jsop_iternext.
+ Bailout_NonStringInputInvalidate,
+
+ // Used for integer division, multiplication and modulo.
+ // If there's a remainder, bails to return a double.
+ // Can also signal overflow or result of -0.
+ // Can also signal division by 0 (returns inf, a double).
+ Bailout_DoubleOutput,
+
+ // END Invalid assumptions bailouts
+
+
+ // A bailout at the very start of a function indicates that there may be
+ // a type mismatch in the arguments that necessitates a reflow.
+ Bailout_ArgumentCheck,
+
+ // A bailout triggered by a bounds-check failure.
+ Bailout_BoundsCheck,
+ // A bailout triggered by a typed object whose backing buffer was detached.
+ Bailout_Detached,
+
+ // A shape guard based on TI information failed.
+ // (We saw an object whose shape does not match that / any of those observed
+ // by the baseline IC.)
+ Bailout_ShapeGuard,
+
+ // When we're trying to use an uninitialized lexical.
+ Bailout_UninitializedLexical,
+
+ // A bailout to baseline from Ion on exception to handle Debugger hooks.
+ Bailout_IonExceptionDebugMode
+};
+
+inline const char*
+BailoutKindString(BailoutKind kind)
+{
+ switch (kind) {
+ // Normal bailouts.
+ case Bailout_Inevitable:
+ return "Bailout_Inevitable";
+ case Bailout_DuringVMCall:
+ return "Bailout_DuringVMCall";
+ case Bailout_NonJSFunctionCallee:
+ return "Bailout_NonJSFunctionCallee";
+ case Bailout_DynamicNameNotFound:
+ return "Bailout_DynamicNameNotFound";
+ case Bailout_StringArgumentsEval:
+ return "Bailout_StringArgumentsEval";
+ case Bailout_Overflow:
+ return "Bailout_Overflow";
+ case Bailout_Round:
+ return "Bailout_Round";
+ case Bailout_NonPrimitiveInput:
+ return "Bailout_NonPrimitiveInput";
+ case Bailout_PrecisionLoss:
+ return "Bailout_PrecisionLoss";
+ case Bailout_TypeBarrierO:
+ return "Bailout_TypeBarrierO";
+ case Bailout_TypeBarrierV:
+ return "Bailout_TypeBarrierV";
+ case Bailout_MonitorTypes:
+ return "Bailout_MonitorTypes";
+ case Bailout_Hole:
+ return "Bailout_Hole";
+ case Bailout_NegativeIndex:
+ return "Bailout_NegativeIndex";
+ case Bailout_ObjectIdentityOrTypeGuard:
+ return "Bailout_ObjectIdentityOrTypeGuard";
+ case Bailout_NonInt32Input:
+ return "Bailout_NonInt32Input";
+ case Bailout_NonNumericInput:
+ return "Bailout_NonNumericInput";
+ case Bailout_NonBooleanInput:
+ return "Bailout_NonBooleanInput";
+ case Bailout_NonObjectInput:
+ return "Bailout_NonObjectInput";
+ case Bailout_NonStringInput:
+ return "Bailout_NonStringInput";
+ case Bailout_NonSymbolInput:
+ return "Bailout_NonSymbolInput";
+ case Bailout_UnexpectedSimdInput:
+ return "Bailout_UnexpectedSimdInput";
+ case Bailout_NonSharedTypedArrayInput:
+ return "Bailout_NonSharedTypedArrayInput";
+ case Bailout_Debugger:
+ return "Bailout_Debugger";
+ case Bailout_UninitializedThis:
+ return "Bailout_UninitializedThis";
+ case Bailout_BadDerivedConstructorReturn:
+ return "Bailout_BadDerivedConstructorReturn";
+ case Bailout_FirstExecution:
+ return "Bailout_FirstExecution";
+
+ // Bailouts caused by invalid assumptions.
+ case Bailout_OverflowInvalidate:
+ return "Bailout_OverflowInvalidate";
+ case Bailout_NonStringInputInvalidate:
+ return "Bailout_NonStringInputInvalidate";
+ case Bailout_DoubleOutput:
+ return "Bailout_DoubleOutput";
+
+ // Other bailouts.
+ case Bailout_ArgumentCheck:
+ return "Bailout_ArgumentCheck";
+ case Bailout_BoundsCheck:
+ return "Bailout_BoundsCheck";
+ case Bailout_Detached:
+ return "Bailout_Detached";
+ case Bailout_ShapeGuard:
+ return "Bailout_ShapeGuard";
+ case Bailout_UninitializedLexical:
+ return "Bailout_UninitializedLexical";
+ case Bailout_IonExceptionDebugMode:
+ return "Bailout_IonExceptionDebugMode";
+ default:
+ MOZ_CRASH("Invalid BailoutKind");
+ }
+}
+
+static const uint32_t ELEMENT_TYPE_BITS = 5;
+static const uint32_t ELEMENT_TYPE_SHIFT = 0;
+static const uint32_t ELEMENT_TYPE_MASK = (1 << ELEMENT_TYPE_BITS) - 1;
+static const uint32_t VECTOR_SCALE_BITS = 3;
+static const uint32_t VECTOR_SCALE_SHIFT = ELEMENT_TYPE_BITS + ELEMENT_TYPE_SHIFT;
+static const uint32_t VECTOR_SCALE_MASK = (1 << VECTOR_SCALE_BITS) - 1;
+
+class SimdConstant {
+ public:
+ enum Type {
+ Int8x16,
+ Int16x8,
+ Int32x4,
+ Float32x4,
+ Undefined = -1
+ };
+
+ typedef int8_t I8x16[16];
+ typedef int16_t I16x8[8];
+ typedef int32_t I32x4[4];
+ typedef float F32x4[4];
+
+ private:
+ Type type_;
+ union {
+ I8x16 i8x16;
+ I16x8 i16x8;
+ I32x4 i32x4;
+ F32x4 f32x4;
+ } u;
+
+ bool defined() const {
+ return type_ != Undefined;
+ }
+
+ public:
+ // Doesn't have a default constructor, as it would prevent it from being
+ // included in unions.
+
+ static SimdConstant CreateX16(const int8_t* array) {
+ SimdConstant cst;
+ cst.type_ = Int8x16;
+ memcpy(cst.u.i8x16, array, sizeof(cst.u));
+ return cst;
+ }
+ static SimdConstant SplatX16(int8_t v) {
+ SimdConstant cst;
+ cst.type_ = Int8x16;
+ std::fill_n(cst.u.i8x16, 16, v);
+ return cst;
+ }
+ static SimdConstant CreateX8(const int16_t* array) {
+ SimdConstant cst;
+ cst.type_ = Int16x8;
+ memcpy(cst.u.i16x8, array, sizeof(cst.u));
+ return cst;
+ }
+ static SimdConstant SplatX8(int16_t v) {
+ SimdConstant cst;
+ cst.type_ = Int16x8;
+ std::fill_n(cst.u.i16x8, 8, v);
+ return cst;
+ }
+ static SimdConstant CreateX4(const int32_t* array) {
+ SimdConstant cst;
+ cst.type_ = Int32x4;
+ memcpy(cst.u.i32x4, array, sizeof(cst.u));
+ return cst;
+ }
+ static SimdConstant SplatX4(int32_t v) {
+ SimdConstant cst;
+ cst.type_ = Int32x4;
+ std::fill_n(cst.u.i32x4, 4, v);
+ return cst;
+ }
+ static SimdConstant CreateX4(const float* array) {
+ SimdConstant cst;
+ cst.type_ = Float32x4;
+ memcpy(cst.u.f32x4, array, sizeof(cst.u));
+ return cst;
+ }
+ static SimdConstant SplatX4(float v) {
+ SimdConstant cst;
+ cst.type_ = Float32x4;
+ std::fill_n(cst.u.f32x4, 4, v);
+ return cst;
+ }
+
+ // Overloads for use by templates.
+ static SimdConstant CreateSimd128(const int8_t* array) { return CreateX16(array); }
+ static SimdConstant CreateSimd128(const int16_t* array) { return CreateX8(array); }
+ static SimdConstant CreateSimd128(const int32_t* array) { return CreateX4(array); }
+ static SimdConstant CreateSimd128(const float* array) { return CreateX4(array); }
+
+ Type type() const {
+ MOZ_ASSERT(defined());
+ return type_;
+ }
+
+ // Get the raw bytes of the constant.
+ const void* bytes() const {
+ return u.i8x16;
+ }
+
+ const I8x16& asInt8x16() const {
+ MOZ_ASSERT(defined() && type_ == Int8x16);
+ return u.i8x16;
+ }
+
+ const I16x8& asInt16x8() const {
+ MOZ_ASSERT(defined() && type_ == Int16x8);
+ return u.i16x8;
+ }
+
+ const I32x4& asInt32x4() const {
+ MOZ_ASSERT(defined() && type_ == Int32x4);
+ return u.i32x4;
+ }
+
+ const F32x4& asFloat32x4() const {
+ MOZ_ASSERT(defined() && type_ == Float32x4);
+ return u.f32x4;
+ }
+
+ bool operator==(const SimdConstant& rhs) const {
+ MOZ_ASSERT(defined() && rhs.defined());
+ if (type() != rhs.type())
+ return false;
+ // Takes negative zero into accuont, as it's a bit comparison.
+ return memcmp(&u, &rhs.u, sizeof(u)) == 0;
+ }
+ bool operator!=(const SimdConstant& rhs) const {
+ return !operator==(rhs);
+ }
+
+ // SimdConstant is a HashPolicy
+ typedef SimdConstant Lookup;
+ static HashNumber hash(const SimdConstant& val) {
+ uint32_t hash = mozilla::HashBytes(&val.u, sizeof(val.u));
+ return mozilla::AddToHash(hash, val.type_);
+ }
+ static bool match(const SimdConstant& lhs, const SimdConstant& rhs) {
+ return lhs == rhs;
+ }
+};
+
+// The ordering of this enumeration is important: Anything < Value is a
+// specialized type. Furthermore, anything < String has trivial conversion to
+// a number.
+enum class MIRType
+{
+ Undefined,
+ Null,
+ Boolean,
+ Int32,
+ Int64,
+ Double,
+ Float32,
+ // Types above have trivial conversion to a number.
+ String,
+ Symbol,
+ // Types above are primitive (including undefined and null).
+ Object,
+ MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value.
+ MagicOptimizedOut, // JS_OPTIMIZED_OUT magic value.
+ MagicHole, // JS_ELEMENTS_HOLE magic value.
+ MagicIsConstructing, // JS_IS_CONSTRUCTING magic value.
+ MagicUninitializedLexical, // JS_UNINITIALIZED_LEXICAL magic value.
+ // Types above are specialized.
+ Value,
+ SinCosDouble, // Optimizing a sin/cos to sincos.
+ ObjectOrNull,
+ None, // Invalid, used as a placeholder.
+ Slots, // A slots vector
+ Elements, // An elements vector
+ Pointer, // An opaque pointer that receives no special treatment
+ Shape, // A Shape pointer.
+ ObjectGroup, // An ObjectGroup pointer.
+ Last = ObjectGroup,
+ // Representing both SIMD.IntBxN and SIMD.UintBxN.
+ Int8x16 = Int32 | (4 << VECTOR_SCALE_SHIFT),
+ Int16x8 = Int32 | (3 << VECTOR_SCALE_SHIFT),
+ Int32x4 = Int32 | (2 << VECTOR_SCALE_SHIFT),
+ Float32x4 = Float32 | (2 << VECTOR_SCALE_SHIFT),
+ Bool8x16 = Boolean | (4 << VECTOR_SCALE_SHIFT),
+ Bool16x8 = Boolean | (3 << VECTOR_SCALE_SHIFT),
+ Bool32x4 = Boolean | (2 << VECTOR_SCALE_SHIFT),
+ Doublex2 = Double | (1 << VECTOR_SCALE_SHIFT)
+};
+
+static inline bool
+IsSimdType(MIRType type)
+{
+ return ((unsigned(type) >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK) != 0;
+}
+
+// Returns the number of vector elements (hereby called "length") for a given
+// SIMD kind. It is the Y part of the name "Foo x Y".
+static inline unsigned
+SimdTypeToLength(MIRType type)
+{
+ MOZ_ASSERT(IsSimdType(type));
+ return 1 << ((unsigned(type) >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK);
+}
+
+// Get the type of the individual lanes in a SIMD type.
+// For example, Int32x4 -> Int32, Float32x4 -> Float32 etc.
+static inline MIRType
+SimdTypeToLaneType(MIRType type)
+{
+ MOZ_ASSERT(IsSimdType(type));
+ static_assert(unsigned(MIRType::Last) <= ELEMENT_TYPE_MASK,
+ "ELEMENT_TYPE_MASK should be larger than the last MIRType");
+ return MIRType((unsigned(type) >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK);
+}
+
+// Get the type expected when inserting a lane into a SIMD type.
+// This is the argument type expected by the MSimdValue constructors as well as
+// MSimdSplat and MSimdInsertElement.
+static inline MIRType
+SimdTypeToLaneArgumentType(MIRType type)
+{
+ MIRType laneType = SimdTypeToLaneType(type);
+
+ // Boolean lanes should be pre-converted to an Int32 with the values 0 or -1.
+ // All other lane types are inserted directly.
+ return laneType == MIRType::Boolean ? MIRType::Int32 : laneType;
+}
+
+static inline MIRType
+MIRTypeFromValueType(JSValueType type)
+{
+ // This function does not deal with magic types. Magic constants should be
+ // filtered out in MIRTypeFromValue.
+ switch (type) {
+ case JSVAL_TYPE_DOUBLE:
+ return MIRType::Double;
+ case JSVAL_TYPE_INT32:
+ return MIRType::Int32;
+ case JSVAL_TYPE_UNDEFINED:
+ return MIRType::Undefined;
+ case JSVAL_TYPE_STRING:
+ return MIRType::String;
+ case JSVAL_TYPE_SYMBOL:
+ return MIRType::Symbol;
+ case JSVAL_TYPE_BOOLEAN:
+ return MIRType::Boolean;
+ case JSVAL_TYPE_NULL:
+ return MIRType::Null;
+ case JSVAL_TYPE_OBJECT:
+ return MIRType::Object;
+ case JSVAL_TYPE_UNKNOWN:
+ return MIRType::Value;
+ default:
+ MOZ_CRASH("unexpected jsval type");
+ }
+}
+
+static inline JSValueType
+ValueTypeFromMIRType(MIRType type)
+{
+ switch (type) {
+ case MIRType::Undefined:
+ return JSVAL_TYPE_UNDEFINED;
+ case MIRType::Null:
+ return JSVAL_TYPE_NULL;
+ case MIRType::Boolean:
+ return JSVAL_TYPE_BOOLEAN;
+ case MIRType::Int32:
+ return JSVAL_TYPE_INT32;
+ case MIRType::Float32: // Fall through, there's no JSVAL for Float32
+ case MIRType::Double:
+ return JSVAL_TYPE_DOUBLE;
+ case MIRType::String:
+ return JSVAL_TYPE_STRING;
+ case MIRType::Symbol:
+ return JSVAL_TYPE_SYMBOL;
+ case MIRType::MagicOptimizedArguments:
+ case MIRType::MagicOptimizedOut:
+ case MIRType::MagicHole:
+ case MIRType::MagicIsConstructing:
+ case MIRType::MagicUninitializedLexical:
+ return JSVAL_TYPE_MAGIC;
+ default:
+ MOZ_ASSERT(type == MIRType::Object);
+ return JSVAL_TYPE_OBJECT;
+ }
+}
+
+static inline JSValueTag
+MIRTypeToTag(MIRType type)
+{
+ return JSVAL_TYPE_TO_TAG(ValueTypeFromMIRType(type));
+}
+
+static inline const char*
+StringFromMIRType(MIRType type)
+{
+ switch (type) {
+ case MIRType::Undefined:
+ return "Undefined";
+ case MIRType::Null:
+ return "Null";
+ case MIRType::Boolean:
+ return "Bool";
+ case MIRType::Int32:
+ return "Int32";
+ case MIRType::Int64:
+ return "Int64";
+ case MIRType::Double:
+ return "Double";
+ case MIRType::Float32:
+ return "Float32";
+ case MIRType::String:
+ return "String";
+ case MIRType::Symbol:
+ return "Symbol";
+ case MIRType::Object:
+ return "Object";
+ case MIRType::MagicOptimizedArguments:
+ return "MagicOptimizedArguments";
+ case MIRType::MagicOptimizedOut:
+ return "MagicOptimizedOut";
+ case MIRType::MagicHole:
+ return "MagicHole";
+ case MIRType::MagicIsConstructing:
+ return "MagicIsConstructing";
+ case MIRType::MagicUninitializedLexical:
+ return "MagicUninitializedLexical";
+ case MIRType::Value:
+ return "Value";
+ case MIRType::SinCosDouble:
+ return "SinCosDouble";
+ case MIRType::ObjectOrNull:
+ return "ObjectOrNull";
+ case MIRType::None:
+ return "None";
+ case MIRType::Slots:
+ return "Slots";
+ case MIRType::Elements:
+ return "Elements";
+ case MIRType::Pointer:
+ return "Pointer";
+ case MIRType::Shape:
+ return "Shape";
+ case MIRType::ObjectGroup:
+ return "ObjectGroup";
+ case MIRType::Int32x4:
+ return "Int32x4";
+ case MIRType::Int16x8:
+ return "Int16x8";
+ case MIRType::Int8x16:
+ return "Int8x16";
+ case MIRType::Float32x4:
+ return "Float32x4";
+ case MIRType::Bool32x4:
+ return "Bool32x4";
+ case MIRType::Bool16x8:
+ return "Bool16x8";
+ case MIRType::Bool8x16:
+ return "Bool8x16";
+ case MIRType::Doublex2:
+ return "Doublex2";
+ }
+ MOZ_CRASH("Unknown MIRType.");
+}
+
+static inline bool
+IsIntType(MIRType type)
+{
+ return type == MIRType::Int32 ||
+ type == MIRType::Int64;
+}
+
+static inline bool
+IsNumberType(MIRType type)
+{
+ return type == MIRType::Int32 ||
+ type == MIRType::Double ||
+ type == MIRType::Float32 ||
+ type == MIRType::Int64;
+}
+
+static inline bool
+IsTypeRepresentableAsDouble(MIRType type)
+{
+ return type == MIRType::Int32 ||
+ type == MIRType::Double ||
+ type == MIRType::Float32;
+}
+
+static inline bool
+IsFloatType(MIRType type)
+{
+ return type == MIRType::Int32 || type == MIRType::Float32;
+}
+
+static inline bool
+IsFloatingPointType(MIRType type)
+{
+ return type == MIRType::Double || type == MIRType::Float32;
+}
+
+static inline bool
+IsNullOrUndefined(MIRType type)
+{
+ return type == MIRType::Null || type == MIRType::Undefined;
+}
+
+static inline bool
+IsFloatingPointSimdType(MIRType type)
+{
+ return type == MIRType::Float32x4;
+}
+
+static inline bool
+IsIntegerSimdType(MIRType type)
+{
+ return IsSimdType(type) && SimdTypeToLaneType(type) == MIRType::Int32;
+}
+
+static inline bool
+IsBooleanSimdType(MIRType type)
+{
+ return IsSimdType(type) && SimdTypeToLaneType(type) == MIRType::Boolean;
+}
+
+static inline bool
+IsMagicType(MIRType type)
+{
+ return type == MIRType::MagicHole ||
+ type == MIRType::MagicOptimizedOut ||
+ type == MIRType::MagicIsConstructing ||
+ type == MIRType::MagicOptimizedArguments ||
+ type == MIRType::MagicUninitializedLexical;
+}
+
+static inline MIRType
+ScalarTypeToMIRType(Scalar::Type type)
+{
+ switch (type) {
+ case Scalar::Int8:
+ case Scalar::Uint8:
+ case Scalar::Int16:
+ case Scalar::Uint16:
+ case Scalar::Int32:
+ case Scalar::Uint32:
+ case Scalar::Uint8Clamped:
+ return MIRType::Int32;
+ case Scalar::Int64:
+ return MIRType::Int64;
+ case Scalar::Float32:
+ return MIRType::Float32;
+ case Scalar::Float64:
+ return MIRType::Double;
+ case Scalar::Float32x4:
+ return MIRType::Float32x4;
+ case Scalar::Int8x16:
+ return MIRType::Int8x16;
+ case Scalar::Int16x8:
+ return MIRType::Int16x8;
+ case Scalar::Int32x4:
+ return MIRType::Int32x4;
+ case Scalar::MaxTypedArrayViewType:
+ break;
+ }
+ MOZ_CRASH("unexpected SIMD kind");
+}
+
+static inline unsigned
+ScalarTypeToLength(Scalar::Type type)
+{
+ switch (type) {
+ case Scalar::Int8:
+ case Scalar::Uint8:
+ case Scalar::Int16:
+ case Scalar::Uint16:
+ case Scalar::Int32:
+ case Scalar::Uint32:
+ case Scalar::Int64:
+ case Scalar::Float32:
+ case Scalar::Float64:
+ case Scalar::Uint8Clamped:
+ return 1;
+ case Scalar::Float32x4:
+ case Scalar::Int32x4:
+ return 4;
+ case Scalar::Int16x8:
+ return 8;
+ case Scalar::Int8x16:
+ return 16;
+ case Scalar::MaxTypedArrayViewType:
+ break;
+ }
+ MOZ_CRASH("unexpected SIMD kind");
+}
+
+static inline const char*
+PropertyNameToExtraName(PropertyName* name)
+{
+ JS::AutoCheckCannotGC nogc;
+ if (!name->hasLatin1Chars())
+ return nullptr;
+ return reinterpret_cast<const char *>(name->latin1Chars(nogc));
+}
+
+#ifdef DEBUG
+
+// Track the pipeline of opcodes which has produced a snapshot.
+#define TRACK_SNAPSHOTS 1
+
+// Make sure registers are not modified between an instruction and
+// its OsiPoint.
+#define CHECK_OSIPOINT_REGISTERS 1
+
+#endif // DEBUG
+
+enum {
+ ArgType_General = 0x1,
+ ArgType_Double = 0x2,
+ ArgType_Float32 = 0x3,
+ ArgType_Int64 = 0x4,
+
+ RetType_Shift = 0x0,
+ ArgType_Shift = 0x3,
+ ArgType_Mask = 0x7
+};
+
+enum ABIFunctionType
+{
+ // VM functions that take 0-9 non-double arguments
+ // and return a non-double value.
+ Args_General0 = ArgType_General << RetType_Shift,
+ Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
+ Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
+ Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
+ Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
+ Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
+ Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
+ Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
+ Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
+
+ // int64 f(double)
+ Args_Int64_Double = (ArgType_Int64 << RetType_Shift) | (ArgType_Double << ArgType_Shift),
+
+ // double f()
+ Args_Double_None = ArgType_Double << RetType_Shift,
+
+ // int f(double)
+ Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift),
+
+ // float f(float)
+ Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
+
+ // double f(double)
+ Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
+
+ // double f(int)
+ Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
+
+ // double f(int, int)
+ Args_Double_IntInt = Args_Double_Int | (ArgType_General << (ArgType_Shift * 2)),
+
+ // double f(double, int)
+ Args_Double_DoubleInt = Args_Double_None |
+ (ArgType_General << (ArgType_Shift * 1)) |
+ (ArgType_Double << (ArgType_Shift * 2)),
+
+ // double f(double, double)
+ Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
+
+ // double f(int, double)
+ Args_Double_IntDouble = Args_Double_None |
+ (ArgType_Double << (ArgType_Shift * 1)) |
+ (ArgType_General << (ArgType_Shift * 2)),
+
+ // int f(int, double)
+ Args_Int_IntDouble = Args_General0 |
+ (ArgType_Double << (ArgType_Shift * 1)) |
+ (ArgType_General << (ArgType_Shift * 2)),
+
+ // double f(double, double, double)
+ Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
+
+ // double f(double, double, double, double)
+ Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4)),
+
+ // int f(double, int, int)
+ Args_Int_DoubleIntInt = Args_General0 |
+ (ArgType_General << (ArgType_Shift * 1)) |
+ (ArgType_General << (ArgType_Shift * 2)) |
+ (ArgType_Double << (ArgType_Shift * 3)),
+
+ // int f(int, double, int, int)
+ Args_Int_IntDoubleIntInt = Args_General0 |
+ (ArgType_General << (ArgType_Shift * 1)) |
+ (ArgType_General << (ArgType_Shift * 2)) |
+ (ArgType_Double << (ArgType_Shift * 3)) |
+ (ArgType_General << (ArgType_Shift * 4))
+
+};
+
+enum class BarrierKind : uint32_t {
+ // No barrier is needed.
+ NoBarrier,
+
+ // The barrier only has to check the value's type tag is in the TypeSet.
+ // Specific object types don't have to be checked.
+ TypeTagOnly,
+
+ // Check if the value is in the TypeSet, including the object type if it's
+ // an object.
+ TypeSet
+};
+
+enum ReprotectCode { Reprotect = true, DontReprotect = false };
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_IonTypes_h */