LCOV - code coverage report
Current view: top level - js/src/jit - IonTypes.h (source / functions) Hit Total Coverage
Test: output.info Lines: 47 231 20.3 %
Date: 2017-07-14 16:53:18 Functions: 8 44 18.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_IonTypes_h
       8             : #define jit_IonTypes_h
       9             : 
      10             : #include "mozilla/HashFunctions.h"
      11             : 
      12             : #include <algorithm>
      13             : 
      14             : #include "jsfriendapi.h"
      15             : #include "jstypes.h"
      16             : 
      17             : #include "js/GCAPI.h"
      18             : #include "js/Value.h"
      19             : #include "vm/String.h"
      20             : 
      21             : namespace js {
      22             : namespace jit {
      23             : 
      24             : typedef uint32_t RecoverOffset;
      25             : typedef uint32_t SnapshotOffset;
      26             : typedef uint32_t BailoutId;
      27             : 
      28             : // The maximum size of any buffer associated with an assembler or code object.
      29             : // This is chosen to not overflow a signed integer, leaving room for an extra
      30             : // bit on offsets.
      31             : static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
      32             : 
      33             : // Maximum number of scripted arg slots.
      34             : static const uint32_t SNAPSHOT_MAX_NARGS = 127;
      35             : 
      36             : static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
      37             : static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
      38             : 
      39             : // Different kinds of bailouts. When extending this enum, make sure to check
      40             : // the bits reserved for bailout kinds in Bailouts.h
      41             : enum BailoutKind
      42             : {
      43             :     // Normal bailouts, that don't need to be handled specially when restarting
      44             :     // in baseline.
      45             : 
      46             :     // An inevitable bailout (MBail instruction or type barrier that always bails)
      47             :     Bailout_Inevitable,
      48             : 
      49             :     // Bailing out during a VM call. Many possible causes that are hard
      50             :     // to distinguish statically at snapshot construction time.
      51             :     // We just lump them together.
      52             :     Bailout_DuringVMCall,
      53             : 
      54             :     // Call to a non-JSFunction (problem for |apply|)
      55             :     Bailout_NonJSFunctionCallee,
      56             : 
      57             :     // Dynamic scope chain lookup produced |undefined|
      58             :     Bailout_DynamicNameNotFound,
      59             : 
      60             :     // Input string contains 'arguments' or 'eval'
      61             :     Bailout_StringArgumentsEval,
      62             : 
      63             :     // Bailout on overflow, but don't immediately invalidate.
      64             :     // Used for abs, sub and LoadUnboxedScalar (when loading a uint32 that
      65             :     // doesn't fit in an int32).
      66             :     Bailout_Overflow,
      67             : 
      68             :     // floor, ceiling and round bail if input is NaN, if output would be -0 or
      69             :     // doesn't fit in int32 range
      70             :     Bailout_Round,
      71             : 
      72             :     // Non-primitive value used as input for ToDouble, ToInt32, ToString, etc.
      73             :     // For ToInt32, can also mean that input can't be converted without precision
      74             :     // loss (e.g. 5.5).
      75             :     Bailout_NonPrimitiveInput,
      76             : 
      77             :     // For ToInt32, would lose precision when converting (e.g. 5.5).
      78             :     Bailout_PrecisionLoss,
      79             : 
      80             :     // We tripped a type barrier (object was not in the expected TypeSet)
      81             :     Bailout_TypeBarrierO,
      82             :     // We tripped a type barrier (value was not in the expected TypeSet)
      83             :     Bailout_TypeBarrierV,
      84             :     // We tripped a type monitor (wrote an unexpected type in a property)
      85             :     Bailout_MonitorTypes,
      86             : 
      87             :     // We hit a hole in an array.
      88             :     Bailout_Hole,
      89             : 
      90             :     // Array access with negative index
      91             :     Bailout_NegativeIndex,
      92             : 
      93             :     // Pretty specific case:
      94             :     //  - need a type barrier on a property write
      95             :     //  - all but one of the observed types have property types that reflect the value
      96             :     //  - we need to guard that we're not given an object of that one other type
      97             :     // also used for the unused GuardClass instruction
      98             :     Bailout_ObjectIdentityOrTypeGuard,
      99             : 
     100             :     // Unbox expects a given type, bails out if it doesn't get it.
     101             :     Bailout_NonInt32Input,
     102             :     Bailout_NonNumericInput, // unboxing a double works with int32 too
     103             :     Bailout_NonBooleanInput,
     104             :     Bailout_NonObjectInput,
     105             :     Bailout_NonStringInput,
     106             :     Bailout_NonSymbolInput,
     107             : 
     108             :     // SIMD Unbox expects a given type, bails out if it doesn't match.
     109             :     Bailout_UnexpectedSimdInput,
     110             : 
     111             :     // Atomic operations require shared memory, bail out if the typed array
     112             :     // maps unshared memory.
     113             :     Bailout_NonSharedTypedArrayInput,
     114             : 
     115             :     // We hit a |debugger;| statement.
     116             :     Bailout_Debugger,
     117             : 
     118             :     // |this| used uninitialized in a derived constructor
     119             :     Bailout_UninitializedThis,
     120             : 
     121             :     // Derived constructors must return object or undefined
     122             :     Bailout_BadDerivedConstructorReturn,
     123             : 
     124             :     // We hit this code for the first time.
     125             :     Bailout_FirstExecution,
     126             : 
     127             :     // END Normal bailouts
     128             : 
     129             :     // Bailouts caused by invalid assumptions based on Baseline code.
     130             :     // Causes immediate invalidation.
     131             : 
     132             :     // Like Bailout_Overflow, but causes immediate invalidation.
     133             :     Bailout_OverflowInvalidate,
     134             : 
     135             :     // Like NonStringInput, but should cause immediate invalidation.
     136             :     // Used for jsop_iternext.
     137             :     Bailout_NonStringInputInvalidate,
     138             : 
     139             :     // Used for integer division, multiplication and modulo.
     140             :     // If there's a remainder, bails to return a double.
     141             :     // Can also signal overflow or result of -0.
     142             :     // Can also signal division by 0 (returns inf, a double).
     143             :     Bailout_DoubleOutput,
     144             : 
     145             :     // END Invalid assumptions bailouts
     146             : 
     147             : 
     148             :     // A bailout at the very start of a function indicates that there may be
     149             :     // a type mismatch in the arguments that necessitates a reflow.
     150             :     Bailout_ArgumentCheck,
     151             : 
     152             :     // A bailout triggered by a bounds-check failure.
     153             :     Bailout_BoundsCheck,
     154             :     // A bailout triggered by a typed object whose backing buffer was detached.
     155             :     Bailout_Detached,
     156             : 
     157             :     // A shape guard based on TI information failed.
     158             :     // (We saw an object whose shape does not match that / any of those observed
     159             :     // by the baseline IC.)
     160             :     Bailout_ShapeGuard,
     161             : 
     162             :     // When we're trying to use an uninitialized lexical.
     163             :     Bailout_UninitializedLexical,
     164             : 
     165             :     // A bailout to baseline from Ion on exception to handle Debugger hooks.
     166             :     Bailout_IonExceptionDebugMode
     167             : };
     168             : 
     169             : inline const char*
     170           0 : BailoutKindString(BailoutKind kind)
     171             : {
     172           0 :     switch (kind) {
     173             :       // Normal bailouts.
     174             :       case Bailout_Inevitable:
     175           0 :         return "Bailout_Inevitable";
     176             :       case Bailout_DuringVMCall:
     177           0 :         return "Bailout_DuringVMCall";
     178             :       case Bailout_NonJSFunctionCallee:
     179           0 :         return "Bailout_NonJSFunctionCallee";
     180             :       case Bailout_DynamicNameNotFound:
     181           0 :         return "Bailout_DynamicNameNotFound";
     182             :       case Bailout_StringArgumentsEval:
     183           0 :         return "Bailout_StringArgumentsEval";
     184             :       case Bailout_Overflow:
     185           0 :         return "Bailout_Overflow";
     186             :       case Bailout_Round:
     187           0 :         return "Bailout_Round";
     188             :       case Bailout_NonPrimitiveInput:
     189           0 :         return "Bailout_NonPrimitiveInput";
     190             :       case Bailout_PrecisionLoss:
     191           0 :         return "Bailout_PrecisionLoss";
     192             :       case Bailout_TypeBarrierO:
     193           0 :         return "Bailout_TypeBarrierO";
     194             :       case Bailout_TypeBarrierV:
     195           0 :         return "Bailout_TypeBarrierV";
     196             :       case Bailout_MonitorTypes:
     197           0 :         return "Bailout_MonitorTypes";
     198             :       case Bailout_Hole:
     199           0 :         return "Bailout_Hole";
     200             :       case Bailout_NegativeIndex:
     201           0 :         return "Bailout_NegativeIndex";
     202             :       case Bailout_ObjectIdentityOrTypeGuard:
     203           0 :         return "Bailout_ObjectIdentityOrTypeGuard";
     204             :       case Bailout_NonInt32Input:
     205           0 :         return "Bailout_NonInt32Input";
     206             :       case Bailout_NonNumericInput:
     207           0 :         return "Bailout_NonNumericInput";
     208             :       case Bailout_NonBooleanInput:
     209           0 :         return "Bailout_NonBooleanInput";
     210             :       case Bailout_NonObjectInput:
     211           0 :         return "Bailout_NonObjectInput";
     212             :       case Bailout_NonStringInput:
     213           0 :         return "Bailout_NonStringInput";
     214             :       case Bailout_NonSymbolInput:
     215           0 :         return "Bailout_NonSymbolInput";
     216             :       case Bailout_UnexpectedSimdInput:
     217           0 :         return "Bailout_UnexpectedSimdInput";
     218             :       case Bailout_NonSharedTypedArrayInput:
     219           0 :         return "Bailout_NonSharedTypedArrayInput";
     220             :       case Bailout_Debugger:
     221           0 :         return "Bailout_Debugger";
     222             :       case Bailout_UninitializedThis:
     223           0 :         return "Bailout_UninitializedThis";
     224             :       case Bailout_BadDerivedConstructorReturn:
     225           0 :         return "Bailout_BadDerivedConstructorReturn";
     226             :       case Bailout_FirstExecution:
     227           0 :         return "Bailout_FirstExecution";
     228             : 
     229             :       // Bailouts caused by invalid assumptions.
     230             :       case Bailout_OverflowInvalidate:
     231           0 :         return "Bailout_OverflowInvalidate";
     232             :       case Bailout_NonStringInputInvalidate:
     233           0 :         return "Bailout_NonStringInputInvalidate";
     234             :       case Bailout_DoubleOutput:
     235           0 :         return "Bailout_DoubleOutput";
     236             : 
     237             :       // Other bailouts.
     238             :       case Bailout_ArgumentCheck:
     239           0 :         return "Bailout_ArgumentCheck";
     240             :       case Bailout_BoundsCheck:
     241           0 :         return "Bailout_BoundsCheck";
     242             :       case Bailout_Detached:
     243           0 :         return "Bailout_Detached";
     244             :       case Bailout_ShapeGuard:
     245           0 :         return "Bailout_ShapeGuard";
     246             :       case Bailout_UninitializedLexical:
     247           0 :         return "Bailout_UninitializedLexical";
     248             :       case Bailout_IonExceptionDebugMode:
     249           0 :         return "Bailout_IonExceptionDebugMode";
     250             :       default:
     251           0 :         MOZ_CRASH("Invalid BailoutKind");
     252             :     }
     253             : }
     254             : 
     255             : static const uint32_t ELEMENT_TYPE_BITS = 5;
     256             : static const uint32_t ELEMENT_TYPE_SHIFT = 0;
     257             : static const uint32_t ELEMENT_TYPE_MASK = (1 << ELEMENT_TYPE_BITS) - 1;
     258             : static const uint32_t VECTOR_SCALE_BITS = 3;
     259             : static const uint32_t VECTOR_SCALE_SHIFT = ELEMENT_TYPE_BITS + ELEMENT_TYPE_SHIFT;
     260             : static const uint32_t VECTOR_SCALE_MASK = (1 << VECTOR_SCALE_BITS) - 1;
     261             : 
     262             : class SimdConstant {
     263             :   public:
     264             :     enum Type {
     265             :         Int8x16,
     266             :         Int16x8,
     267             :         Int32x4,
     268             :         Float32x4,
     269             :         Undefined = -1
     270             :     };
     271             : 
     272             :     typedef int8_t I8x16[16];
     273             :     typedef int16_t I16x8[8];
     274             :     typedef int32_t I32x4[4];
     275             :     typedef float F32x4[4];
     276             : 
     277             :   private:
     278             :     Type type_;
     279             :     union {
     280             :         I8x16 i8x16;
     281             :         I16x8 i16x8;
     282             :         I32x4 i32x4;
     283             :         F32x4 f32x4;
     284             :     } u;
     285             : 
     286           0 :     bool defined() const {
     287           0 :         return type_ != Undefined;
     288             :     }
     289             : 
     290             :   public:
     291             :     // Doesn't have a default constructor, as it would prevent it from being
     292             :     // included in unions.
     293             : 
     294           0 :     static SimdConstant CreateX16(const int8_t* array) {
     295             :         SimdConstant cst;
     296           0 :         cst.type_ = Int8x16;
     297           0 :         memcpy(cst.u.i8x16, array, sizeof(cst.u));
     298           0 :         return cst;
     299             :     }
     300           0 :     static SimdConstant SplatX16(int8_t v) {
     301             :         SimdConstant cst;
     302           0 :         cst.type_ = Int8x16;
     303           0 :         std::fill_n(cst.u.i8x16, 16, v);
     304           0 :         return cst;
     305             :     }
     306           0 :     static SimdConstant CreateX8(const int16_t* array) {
     307             :         SimdConstant cst;
     308           0 :         cst.type_ = Int16x8;
     309           0 :         memcpy(cst.u.i16x8, array, sizeof(cst.u));
     310           0 :         return cst;
     311             :     }
     312           0 :     static SimdConstant SplatX8(int16_t v) {
     313             :         SimdConstant cst;
     314           0 :         cst.type_ = Int16x8;
     315           0 :         std::fill_n(cst.u.i16x8, 8, v);
     316           0 :         return cst;
     317             :     }
     318           0 :     static SimdConstant CreateX4(const int32_t* array) {
     319             :         SimdConstant cst;
     320           0 :         cst.type_ = Int32x4;
     321           0 :         memcpy(cst.u.i32x4, array, sizeof(cst.u));
     322           0 :         return cst;
     323             :     }
     324           0 :     static SimdConstant SplatX4(int32_t v) {
     325             :         SimdConstant cst;
     326           0 :         cst.type_ = Int32x4;
     327           0 :         std::fill_n(cst.u.i32x4, 4, v);
     328           0 :         return cst;
     329             :     }
     330           0 :     static SimdConstant CreateX4(const float* array) {
     331             :         SimdConstant cst;
     332           0 :         cst.type_ = Float32x4;
     333           0 :         memcpy(cst.u.f32x4, array, sizeof(cst.u));
     334           0 :         return cst;
     335             :     }
     336           0 :     static SimdConstant SplatX4(float v) {
     337             :         SimdConstant cst;
     338           0 :         cst.type_ = Float32x4;
     339           0 :         std::fill_n(cst.u.f32x4, 4, v);
     340           0 :         return cst;
     341             :     }
     342             : 
     343             :     // Overloads for use by templates.
     344           0 :     static SimdConstant CreateSimd128(const int8_t* array) { return CreateX16(array); }
     345           0 :     static SimdConstant CreateSimd128(const int16_t* array) { return CreateX8(array); }
     346           0 :     static SimdConstant CreateSimd128(const int32_t* array) { return CreateX4(array); }
     347           0 :     static SimdConstant CreateSimd128(const float* array) { return CreateX4(array); }
     348             : 
     349           0 :     Type type() const {
     350           0 :         MOZ_ASSERT(defined());
     351           0 :         return type_;
     352             :     }
     353             : 
     354             :     // Get the raw bytes of the constant.
     355           0 :     const void* bytes() const {
     356           0 :         return u.i8x16;
     357             :     }
     358             : 
     359           0 :     const I8x16& asInt8x16() const {
     360           0 :         MOZ_ASSERT(defined() && type_ == Int8x16);
     361           0 :         return u.i8x16;
     362             :     }
     363             : 
     364           0 :     const I16x8& asInt16x8() const {
     365           0 :         MOZ_ASSERT(defined() && type_ == Int16x8);
     366           0 :         return u.i16x8;
     367             :     }
     368             : 
     369           0 :     const I32x4& asInt32x4() const {
     370           0 :         MOZ_ASSERT(defined() && type_ == Int32x4);
     371           0 :         return u.i32x4;
     372             :     }
     373             : 
     374           0 :     const F32x4& asFloat32x4() const {
     375           0 :         MOZ_ASSERT(defined() && type_ == Float32x4);
     376           0 :         return u.f32x4;
     377             :     }
     378             : 
     379           0 :     bool operator==(const SimdConstant& rhs) const {
     380           0 :         MOZ_ASSERT(defined() && rhs.defined());
     381           0 :         if (type() != rhs.type())
     382           0 :             return false;
     383             :         // Takes negative zero into accuont, as it's a bit comparison.
     384           0 :         return memcmp(&u, &rhs.u, sizeof(u)) == 0;
     385             :     }
     386             :     bool operator!=(const SimdConstant& rhs) const {
     387             :         return !operator==(rhs);
     388             :     }
     389             : 
     390             :     // SimdConstant is a HashPolicy
     391             :     typedef SimdConstant Lookup;
     392           0 :     static HashNumber hash(const SimdConstant& val) {
     393           0 :         uint32_t hash = mozilla::HashBytes(&val.u, sizeof(val.u));
     394           0 :         return mozilla::AddToHash(hash, val.type_);
     395             :     }
     396           0 :     static bool match(const SimdConstant& lhs, const SimdConstant& rhs) {
     397           0 :         return lhs == rhs;
     398             :     }
     399             : };
     400             : 
     401             : // The ordering of this enumeration is important: Anything < Value is a
     402             : // specialized type. Furthermore, anything < String has trivial conversion to
     403             : // a number.
     404             : enum class MIRType
     405             : {
     406             :     Undefined,
     407             :     Null,
     408             :     Boolean,
     409             :     Int32,
     410             :     Int64,
     411             :     Double,
     412             :     Float32,
     413             :     // Types above have trivial conversion to a number.
     414             :     String,
     415             :     Symbol,
     416             :     // Types above are primitive (including undefined and null).
     417             :     Object,
     418             :     MagicOptimizedArguments,   // JS_OPTIMIZED_ARGUMENTS magic value.
     419             :     MagicOptimizedOut,         // JS_OPTIMIZED_OUT magic value.
     420             :     MagicHole,                 // JS_ELEMENTS_HOLE magic value.
     421             :     MagicIsConstructing,       // JS_IS_CONSTRUCTING magic value.
     422             :     MagicUninitializedLexical, // JS_UNINITIALIZED_LEXICAL magic value.
     423             :     // Types above are specialized.
     424             :     Value,
     425             :     SinCosDouble,              // Optimizing a sin/cos to sincos.
     426             :     ObjectOrNull,
     427             :     None,                      // Invalid, used as a placeholder.
     428             :     Slots,                     // A slots vector
     429             :     Elements,                  // An elements vector
     430             :     Pointer,                   // An opaque pointer that receives no special treatment
     431             :     Shape,                     // A Shape pointer.
     432             :     ObjectGroup,               // An ObjectGroup pointer.
     433             :     Last = ObjectGroup,
     434             :     // Representing both SIMD.IntBxN and SIMD.UintBxN.
     435             :     Int8x16   = Int32   | (4 << VECTOR_SCALE_SHIFT),
     436             :     Int16x8   = Int32   | (3 << VECTOR_SCALE_SHIFT),
     437             :     Int32x4   = Int32   | (2 << VECTOR_SCALE_SHIFT),
     438             :     Float32x4 = Float32 | (2 << VECTOR_SCALE_SHIFT),
     439             :     Bool8x16  = Boolean | (4 << VECTOR_SCALE_SHIFT),
     440             :     Bool16x8  = Boolean | (3 << VECTOR_SCALE_SHIFT),
     441             :     Bool32x4  = Boolean | (2 << VECTOR_SCALE_SHIFT),
     442             :     Doublex2  = Double  | (1 << VECTOR_SCALE_SHIFT)
     443             : };
     444             : 
     445             : static inline bool
     446           0 : IsSimdType(MIRType type)
     447             : {
     448           0 :     return ((unsigned(type) >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK) != 0;
     449             : }
     450             : 
     451             : // Returns the number of vector elements (hereby called "length") for a given
     452             : // SIMD kind. It is the Y part of the name "Foo x Y".
     453             : static inline unsigned
     454           0 : SimdTypeToLength(MIRType type)
     455             : {
     456           0 :     MOZ_ASSERT(IsSimdType(type));
     457           0 :     return 1 << ((unsigned(type) >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK);
     458             : }
     459             : 
     460             : // Get the type of the individual lanes in a SIMD type.
     461             : // For example, Int32x4 -> Int32, Float32x4 -> Float32 etc.
     462             : static inline MIRType
     463           0 : SimdTypeToLaneType(MIRType type)
     464             : {
     465           0 :     MOZ_ASSERT(IsSimdType(type));
     466             :     static_assert(unsigned(MIRType::Last) <= ELEMENT_TYPE_MASK,
     467             :                   "ELEMENT_TYPE_MASK should be larger than the last MIRType");
     468           0 :     return MIRType((unsigned(type) >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK);
     469             : }
     470             : 
     471             : // Get the type expected when inserting a lane into a SIMD type.
     472             : // This is the argument type expected by the MSimdValue constructors as well as
     473             : // MSimdSplat and MSimdInsertElement.
     474             : static inline MIRType
     475           0 : SimdTypeToLaneArgumentType(MIRType type)
     476             : {
     477           0 :     MIRType laneType = SimdTypeToLaneType(type);
     478             : 
     479             :     // Boolean lanes should be pre-converted to an Int32 with the values 0 or -1.
     480             :     // All other lane types are inserted directly.
     481           0 :     return laneType == MIRType::Boolean ? MIRType::Int32 : laneType;
     482             : }
     483             : 
     484             : static inline MIRType
     485        5007 : MIRTypeFromValueType(JSValueType type)
     486             : {
     487             :     // This function does not deal with magic types. Magic constants should be
     488             :     // filtered out in MIRTypeFromValue.
     489        5007 :     switch (type) {
     490             :       case JSVAL_TYPE_DOUBLE:
     491           1 :         return MIRType::Double;
     492             :       case JSVAL_TYPE_INT32:
     493        2213 :         return MIRType::Int32;
     494             :       case JSVAL_TYPE_UNDEFINED:
     495        1722 :         return MIRType::Undefined;
     496             :       case JSVAL_TYPE_STRING:
     497         180 :         return MIRType::String;
     498             :       case JSVAL_TYPE_SYMBOL:
     499           5 :         return MIRType::Symbol;
     500             :       case JSVAL_TYPE_BOOLEAN:
     501         258 :         return MIRType::Boolean;
     502             :       case JSVAL_TYPE_NULL:
     503          47 :         return MIRType::Null;
     504             :       case JSVAL_TYPE_OBJECT:
     505         581 :         return MIRType::Object;
     506             :       case JSVAL_TYPE_UNKNOWN:
     507           0 :         return MIRType::Value;
     508             :       default:
     509           0 :         MOZ_CRASH("unexpected jsval type");
     510             :     }
     511             : }
     512             : 
     513             : static inline JSValueType
     514        5095 : ValueTypeFromMIRType(MIRType type)
     515             : {
     516        5095 :   switch (type) {
     517             :     case MIRType::Undefined:
     518         287 :       return JSVAL_TYPE_UNDEFINED;
     519             :     case MIRType::Null:
     520           3 :       return JSVAL_TYPE_NULL;
     521             :     case MIRType::Boolean:
     522        2125 :       return JSVAL_TYPE_BOOLEAN;
     523             :     case MIRType::Int32:
     524         479 :       return JSVAL_TYPE_INT32;
     525             :     case MIRType::Float32: // Fall through, there's no JSVAL for Float32
     526             :     case MIRType::Double:
     527           1 :       return JSVAL_TYPE_DOUBLE;
     528             :     case MIRType::String:
     529         340 :       return JSVAL_TYPE_STRING;
     530             :     case MIRType::Symbol:
     531           0 :       return JSVAL_TYPE_SYMBOL;
     532             :     case MIRType::MagicOptimizedArguments:
     533             :     case MIRType::MagicOptimizedOut:
     534             :     case MIRType::MagicHole:
     535             :     case MIRType::MagicIsConstructing:
     536             :     case MIRType::MagicUninitializedLexical:
     537           2 :       return JSVAL_TYPE_MAGIC;
     538             :     default:
     539        1858 :       MOZ_ASSERT(type == MIRType::Object);
     540        1858 :       return JSVAL_TYPE_OBJECT;
     541             :   }
     542             : }
     543             : 
     544             : static inline JSValueTag
     545           0 : MIRTypeToTag(MIRType type)
     546             : {
     547           0 :     return JSVAL_TYPE_TO_TAG(ValueTypeFromMIRType(type));
     548             : }
     549             : 
     550             : static inline const char*
     551         143 : StringFromMIRType(MIRType type)
     552             : {
     553         143 :   switch (type) {
     554             :     case MIRType::Undefined:
     555           0 :       return "Undefined";
     556             :     case MIRType::Null:
     557           0 :       return "Null";
     558             :     case MIRType::Boolean:
     559          40 :       return "Bool";
     560             :     case MIRType::Int32:
     561          16 :       return "Int32";
     562             :     case MIRType::Int64:
     563           0 :       return "Int64";
     564             :     case MIRType::Double:
     565           1 :       return "Double";
     566             :     case MIRType::Float32:
     567           0 :       return "Float32";
     568             :     case MIRType::String:
     569          32 :       return "String";
     570             :     case MIRType::Symbol:
     571           0 :       return "Symbol";
     572             :     case MIRType::Object:
     573          54 :       return "Object";
     574             :     case MIRType::MagicOptimizedArguments:
     575           0 :       return "MagicOptimizedArguments";
     576             :     case MIRType::MagicOptimizedOut:
     577           0 :       return "MagicOptimizedOut";
     578             :     case MIRType::MagicHole:
     579           0 :       return "MagicHole";
     580             :     case MIRType::MagicIsConstructing:
     581           0 :       return "MagicIsConstructing";
     582             :     case MIRType::MagicUninitializedLexical:
     583           0 :       return "MagicUninitializedLexical";
     584             :     case MIRType::Value:
     585           0 :       return "Value";
     586             :     case MIRType::SinCosDouble:
     587           0 :       return "SinCosDouble";
     588             :     case MIRType::ObjectOrNull:
     589           0 :       return "ObjectOrNull";
     590             :     case MIRType::None:
     591           0 :       return "None";
     592             :     case MIRType::Slots:
     593           0 :       return "Slots";
     594             :     case MIRType::Elements:
     595           0 :       return "Elements";
     596             :     case MIRType::Pointer:
     597           0 :       return "Pointer";
     598             :     case MIRType::Shape:
     599           0 :       return "Shape";
     600             :     case MIRType::ObjectGroup:
     601           0 :       return "ObjectGroup";
     602             :     case MIRType::Int32x4:
     603           0 :       return "Int32x4";
     604             :     case MIRType::Int16x8:
     605           0 :       return "Int16x8";
     606             :     case MIRType::Int8x16:
     607           0 :       return "Int8x16";
     608             :     case MIRType::Float32x4:
     609           0 :       return "Float32x4";
     610             :     case MIRType::Bool32x4:
     611           0 :       return "Bool32x4";
     612             :     case MIRType::Bool16x8:
     613           0 :       return "Bool16x8";
     614             :     case MIRType::Bool8x16:
     615           0 :       return "Bool8x16";
     616             :     case MIRType::Doublex2:
     617           0 :       return "Doublex2";
     618             :   }
     619           0 :   MOZ_CRASH("Unknown MIRType.");
     620             : }
     621             : 
     622             : static inline bool
     623           0 : IsIntType(MIRType type)
     624             : {
     625           0 :     return type == MIRType::Int32 ||
     626           0 :            type == MIRType::Int64;
     627             : }
     628             : 
     629             : static inline bool
     630         480 : IsNumberType(MIRType type)
     631             : {
     632         107 :     return type == MIRType::Int32 ||
     633          68 :            type == MIRType::Double ||
     634         548 :            type == MIRType::Float32 ||
     635         480 :            type == MIRType::Int64;
     636             : }
     637             : 
     638             : static inline bool
     639        1873 : IsTypeRepresentableAsDouble(MIRType type)
     640             : {
     641        1105 :     return type == MIRType::Int32 ||
     642        2871 :            type == MIRType::Double ||
     643        1873 :            type == MIRType::Float32;
     644             : }
     645             : 
     646             : static inline bool
     647           0 : IsFloatType(MIRType type)
     648             : {
     649           0 :     return type == MIRType::Int32 || type == MIRType::Float32;
     650             : }
     651             : 
     652             : static inline bool
     653        1104 : IsFloatingPointType(MIRType type)
     654             : {
     655        1104 :     return type == MIRType::Double || type == MIRType::Float32;
     656             : }
     657             : 
     658             : static inline bool
     659        3531 : IsNullOrUndefined(MIRType type)
     660             : {
     661        3531 :     return type == MIRType::Null || type == MIRType::Undefined;
     662             : }
     663             : 
     664             : static inline bool
     665           0 : IsFloatingPointSimdType(MIRType type)
     666             : {
     667           0 :     return type == MIRType::Float32x4;
     668             : }
     669             : 
     670             : static inline bool
     671           0 : IsIntegerSimdType(MIRType type)
     672             : {
     673           0 :     return IsSimdType(type) && SimdTypeToLaneType(type) == MIRType::Int32;
     674             : }
     675             : 
     676             : static inline bool
     677           0 : IsBooleanSimdType(MIRType type)
     678             : {
     679           0 :     return IsSimdType(type) && SimdTypeToLaneType(type) == MIRType::Boolean;
     680             : }
     681             : 
     682             : static inline bool
     683        1799 : IsMagicType(MIRType type)
     684             : {
     685        1799 :     return type == MIRType::MagicHole ||
     686         117 :            type == MIRType::MagicOptimizedOut ||
     687         103 :            type == MIRType::MagicIsConstructing ||
     688        1899 :            type == MIRType::MagicOptimizedArguments ||
     689        1799 :            type == MIRType::MagicUninitializedLexical;
     690             : }
     691             : 
     692             : static inline MIRType
     693           0 : ScalarTypeToMIRType(Scalar::Type type)
     694             : {
     695           0 :     switch (type) {
     696             :       case Scalar::Int8:
     697             :       case Scalar::Uint8:
     698             :       case Scalar::Int16:
     699             :       case Scalar::Uint16:
     700             :       case Scalar::Int32:
     701             :       case Scalar::Uint32:
     702             :       case Scalar::Uint8Clamped:
     703           0 :         return MIRType::Int32;
     704             :       case Scalar::Int64:
     705           0 :         return MIRType::Int64;
     706             :       case Scalar::Float32:
     707           0 :         return MIRType::Float32;
     708             :       case Scalar::Float64:
     709           0 :         return MIRType::Double;
     710             :       case Scalar::Float32x4:
     711           0 :         return MIRType::Float32x4;
     712             :       case Scalar::Int8x16:
     713           0 :         return MIRType::Int8x16;
     714             :       case Scalar::Int16x8:
     715           0 :         return MIRType::Int16x8;
     716             :       case Scalar::Int32x4:
     717           0 :         return MIRType::Int32x4;
     718             :       case Scalar::MaxTypedArrayViewType:
     719           0 :         break;
     720             :     }
     721           0 :     MOZ_CRASH("unexpected SIMD kind");
     722             : }
     723             : 
     724             : static inline unsigned
     725           0 : ScalarTypeToLength(Scalar::Type type)
     726             : {
     727           0 :     switch (type) {
     728             :       case Scalar::Int8:
     729             :       case Scalar::Uint8:
     730             :       case Scalar::Int16:
     731             :       case Scalar::Uint16:
     732             :       case Scalar::Int32:
     733             :       case Scalar::Uint32:
     734             :       case Scalar::Int64:
     735             :       case Scalar::Float32:
     736             :       case Scalar::Float64:
     737             :       case Scalar::Uint8Clamped:
     738           0 :         return 1;
     739             :       case Scalar::Float32x4:
     740             :       case Scalar::Int32x4:
     741           0 :         return 4;
     742             :       case Scalar::Int16x8:
     743           0 :         return 8;
     744             :       case Scalar::Int8x16:
     745           0 :         return 16;
     746             :       case Scalar::MaxTypedArrayViewType:
     747           0 :         break;
     748             :     }
     749           0 :     MOZ_CRASH("unexpected SIMD kind");
     750             : }
     751             : 
     752             : static inline const char*
     753           0 : PropertyNameToExtraName(PropertyName* name)
     754             : {
     755           0 :     JS::AutoCheckCannotGC nogc;
     756           0 :     if (!name->hasLatin1Chars())
     757           0 :         return nullptr;
     758           0 :     return reinterpret_cast<const char *>(name->latin1Chars(nogc));
     759             : }
     760             : 
     761             : #ifdef DEBUG
     762             : 
     763             : // Track the pipeline of opcodes which has produced a snapshot.
     764             : #define TRACK_SNAPSHOTS 1
     765             : 
     766             : // Make sure registers are not modified between an instruction and
     767             : // its OsiPoint.
     768             : #define CHECK_OSIPOINT_REGISTERS 1
     769             : 
     770             : #endif // DEBUG
     771             : 
     772             : enum ABIArgType {
     773             :     ArgType_General = 0x1,
     774             :     ArgType_Double  = 0x2,
     775             :     ArgType_Float32 = 0x3,
     776             :     ArgType_Int64   = 0x4,
     777             : 
     778             :     RetType_Shift   = 0x0,
     779             :     ArgType_Shift   = 0x3,
     780             :     ArgType_Mask    = 0x7
     781             : };
     782             : 
     783             : enum ABIFunctionType
     784             : {
     785             :     // VM functions that take 0-9 non-double arguments
     786             :     // and return a non-double value.
     787             :     Args_General0 = ArgType_General << RetType_Shift,
     788             :     Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
     789             :     Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
     790             :     Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
     791             :     Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
     792             :     Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
     793             :     Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
     794             :     Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
     795             :     Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
     796             : 
     797             :     // int64 f(double)
     798             :     Args_Int64_Double = (ArgType_Int64 << RetType_Shift) | (ArgType_Double << ArgType_Shift),
     799             : 
     800             :     // double f()
     801             :     Args_Double_None = ArgType_Double << RetType_Shift,
     802             : 
     803             :     // int f(double)
     804             :     Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift),
     805             : 
     806             :     // float f(float)
     807             :     Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
     808             : 
     809             :     // float f(int, int)
     810             :     Args_Float32_IntInt = (ArgType_Float32 << RetType_Shift) |
     811             :         (ArgType_General << (ArgType_Shift * 1)) |
     812             :         (ArgType_General << (ArgType_Shift * 2)),
     813             : 
     814             :     // double f(double)
     815             :     Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
     816             : 
     817             :     // double f(int)
     818             :     Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
     819             : 
     820             :     // double f(int, int)
     821             :     Args_Double_IntInt = Args_Double_Int | (ArgType_General << (ArgType_Shift * 2)),
     822             : 
     823             :     // double f(double, int)
     824             :     Args_Double_DoubleInt = Args_Double_None |
     825             :         (ArgType_General << (ArgType_Shift * 1)) |
     826             :         (ArgType_Double << (ArgType_Shift * 2)),
     827             : 
     828             :     // double f(double, double)
     829             :     Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
     830             : 
     831             :     // float f(float, float)
     832             :     Args_Float32_Float32Float32 = Args_Float32_Float32 | (ArgType_Float32 << (ArgType_Shift * 2)),
     833             : 
     834             :     // double f(int, double)
     835             :     Args_Double_IntDouble = Args_Double_None |
     836             :         (ArgType_Double << (ArgType_Shift * 1)) |
     837             :         (ArgType_General << (ArgType_Shift * 2)),
     838             : 
     839             :     // int f(int, double)
     840             :     Args_Int_IntDouble = Args_General0 |
     841             :         (ArgType_Double << (ArgType_Shift * 1)) |
     842             :         (ArgType_General << (ArgType_Shift * 2)),
     843             : 
     844             :     // double f(double, double, double)
     845             :     Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
     846             : 
     847             :     // double f(double, double, double, double)
     848             :     Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4)),
     849             : 
     850             :     // int f(double, int, int)
     851             :     Args_Int_DoubleIntInt = Args_General0 |
     852             :        (ArgType_General << (ArgType_Shift * 1)) |
     853             :        (ArgType_General << (ArgType_Shift * 2)) |
     854             :        (ArgType_Double  << (ArgType_Shift * 3)),
     855             : 
     856             :     // int f(int, double, int, int)
     857             :     Args_Int_IntDoubleIntInt = Args_General0 |
     858             :         (ArgType_General << (ArgType_Shift * 1)) |
     859             :         (ArgType_General << (ArgType_Shift * 2)) |
     860             :         (ArgType_Double  << (ArgType_Shift * 3)) |
     861             :         (ArgType_General << (ArgType_Shift * 4))
     862             : };
     863             : 
     864             : enum class BarrierKind : uint32_t {
     865             :     // No barrier is needed.
     866             :     NoBarrier,
     867             : 
     868             :     // The barrier only has to check the value's type tag is in the TypeSet.
     869             :     // Specific object types don't have to be checked.
     870             :     TypeTagOnly,
     871             : 
     872             :     // Check if the value is in the TypeSet, including the object type if it's
     873             :     // an object.
     874             :     TypeSet
     875             : };
     876             : 
     877             : enum ReprotectCode { Reprotect = true, DontReprotect = false };
     878             : 
     879             : // Rounding modes for round instructions.
     880             : enum class RoundingMode {
     881             :     Down,
     882             :     Up,
     883             :     NearestTiesToEven,
     884             :     TowardsZero
     885             : };
     886             : 
     887             : } // namespace jit
     888             : } // namespace js
     889             : 
     890             : #endif /* jit_IonTypes_h */

Generated by: LCOV version 1.13