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 "jsfriendapi.h"
13 #include "jstypes.h"
14 
15 #include "js/Value.h"
16 
17 namespace js {
18 namespace jit {
19 
20 typedef uint32_t RecoverOffset;
21 typedef uint32_t SnapshotOffset;
22 typedef uint32_t BailoutId;
23 
24 // The maximum size of any buffer associated with an assembler or code object.
25 // This is chosen to not overflow a signed integer, leaving room for an extra
26 // bit on offsets.
27 static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
28 
29 // Maximum number of scripted arg slots.
30 static const uint32_t SNAPSHOT_MAX_NARGS = 127;
31 
32 static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
33 static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
34 
35 // Different kinds of bailouts. When extending this enum, make sure to check
36 // the bits reserved for bailout kinds in Bailouts.h
37 enum BailoutKind
38 {
39     // Normal bailouts, that don't need to be handled specially when restarting
40     // in baseline.
41 
42     // An inevitable bailout (MBail instruction or type barrier that always bails)
43     Bailout_Inevitable,
44 
45     // Bailing out during a VM call. Many possible causes that are hard
46     // to distinguish statically at snapshot construction time.
47     // We just lump them together.
48     Bailout_DuringVMCall,
49 
50     // Call to a non-JSFunction (problem for |apply|)
51     Bailout_NonJSFunctionCallee,
52 
53     // Dynamic scope chain lookup produced |undefined|
54     Bailout_DynamicNameNotFound,
55 
56     // Input string contains 'arguments' or 'eval'
57     Bailout_StringArgumentsEval,
58 
59     // Bailout on overflow, but don't immediately invalidate.
60     // Used for abs, sub and LoadUnboxedScalar (when loading a uint32 that
61     // doesn't fit in an int32).
62     Bailout_Overflow,
63 
64     // floor, ceiling and round bail if input is NaN, if output would be -0 or
65     // doesn't fit in int32 range
66     Bailout_Round,
67 
68     // Non-primitive value used as input for ToDouble, ToInt32, ToString, etc.
69     // For ToInt32, can also mean that input can't be converted without precision
70     // loss (e.g. 5.5).
71     Bailout_NonPrimitiveInput,
72 
73     // For ToInt32, would lose precision when converting (e.g. 5.5).
74     Bailout_PrecisionLoss,
75 
76     // We tripped a type barrier (object was not in the expected TypeSet)
77     Bailout_TypeBarrierO,
78     // We tripped a type barrier (value was not in the expected TypeSet)
79     Bailout_TypeBarrierV,
80     // We tripped a type monitor (wrote an unexpected type in a property)
81     Bailout_MonitorTypes,
82 
83     // We hit a hole in an array.
84     Bailout_Hole,
85 
86     // Array access with negative index
87     Bailout_NegativeIndex,
88 
89     // Pretty specific case:
90     //  - need a type barrier on a property write
91     //  - all but one of the observed types have property types that reflect the value
92     //  - we need to guard that we're not given an object of that one other type
93     // also used for the unused GuardClass instruction
94     Bailout_ObjectIdentityOrTypeGuard,
95 
96     // Unbox expects a given type, bails out if it doesn't get it.
97     Bailout_NonInt32Input,
98     Bailout_NonNumericInput, // unboxing a double works with int32 too
99     Bailout_NonBooleanInput,
100     Bailout_NonObjectInput,
101     Bailout_NonStringInput,
102     Bailout_NonSymbolInput,
103 
104     // SIMD Unbox expects a given type, bails out if it doesn't match.
105     Bailout_NonSimdInt32x4Input,
106     Bailout_NonSimdFloat32x4Input,
107 
108     // Atomic operations require shared memory, bail out if the typed array
109     // maps unshared memory.
110     Bailout_NonSharedTypedArrayInput,
111 
112     // For the initial snapshot when entering a function.
113     Bailout_InitialState,
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 neutered typed object.
155     Bailout_Neutered,
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*
BailoutKindString(BailoutKind kind)170 BailoutKindString(BailoutKind kind)
171 {
172     switch (kind) {
173       // Normal bailouts.
174       case Bailout_Inevitable:
175         return "Bailout_Inevitable";
176       case Bailout_DuringVMCall:
177         return "Bailout_DuringVMCall";
178       case Bailout_NonJSFunctionCallee:
179         return "Bailout_NonJSFunctionCallee";
180       case Bailout_DynamicNameNotFound:
181         return "Bailout_DynamicNameNotFound";
182       case Bailout_StringArgumentsEval:
183         return "Bailout_StringArgumentsEval";
184       case Bailout_Overflow:
185         return "Bailout_Overflow";
186       case Bailout_Round:
187         return "Bailout_Round";
188       case Bailout_NonPrimitiveInput:
189         return "Bailout_NonPrimitiveInput";
190       case Bailout_PrecisionLoss:
191         return "Bailout_PrecisionLoss";
192       case Bailout_TypeBarrierO:
193         return "Bailout_TypeBarrierO";
194       case Bailout_TypeBarrierV:
195         return "Bailout_TypeBarrierV";
196       case Bailout_MonitorTypes:
197         return "Bailout_MonitorTypes";
198       case Bailout_Hole:
199         return "Bailout_Hole";
200       case Bailout_NegativeIndex:
201         return "Bailout_NegativeIndex";
202       case Bailout_ObjectIdentityOrTypeGuard:
203         return "Bailout_ObjectIdentityOrTypeGuard";
204       case Bailout_NonInt32Input:
205         return "Bailout_NonInt32Input";
206       case Bailout_NonNumericInput:
207         return "Bailout_NonNumericInput";
208       case Bailout_NonBooleanInput:
209         return "Bailout_NonBooleanInput";
210       case Bailout_NonObjectInput:
211         return "Bailout_NonObjectInput";
212       case Bailout_NonStringInput:
213         return "Bailout_NonStringInput";
214       case Bailout_NonSymbolInput:
215         return "Bailout_NonSymbolInput";
216       case Bailout_NonSimdInt32x4Input:
217         return "Bailout_NonSimdInt32x4Input";
218       case Bailout_NonSimdFloat32x4Input:
219         return "Bailout_NonSimdFloat32x4Input";
220       case Bailout_NonSharedTypedArrayInput:
221         return "Bailout_NonSharedTypedArrayInput";
222       case Bailout_InitialState:
223         return "Bailout_InitialState";
224       case Bailout_Debugger:
225         return "Bailout_Debugger";
226       case Bailout_UninitializedThis:
227         return "Bailout_UninitializedThis";
228       case Bailout_BadDerivedConstructorReturn:
229         return "Bailout_BadDerivedConstructorReturn";
230       case Bailout_FirstExecution:
231         return "Bailout_FirstExecution";
232 
233       // Bailouts caused by invalid assumptions.
234       case Bailout_OverflowInvalidate:
235         return "Bailout_OverflowInvalidate";
236       case Bailout_NonStringInputInvalidate:
237         return "Bailout_NonStringInputInvalidate";
238       case Bailout_DoubleOutput:
239         return "Bailout_DoubleOutput";
240 
241       // Other bailouts.
242       case Bailout_ArgumentCheck:
243         return "Bailout_ArgumentCheck";
244       case Bailout_BoundsCheck:
245         return "Bailout_BoundsCheck";
246       case Bailout_Neutered:
247         return "Bailout_Neutered";
248       case Bailout_ShapeGuard:
249         return "Bailout_ShapeGuard";
250       case Bailout_UninitializedLexical:
251         return "Bailout_UninitializedLexical";
252       case Bailout_IonExceptionDebugMode:
253         return "Bailout_IonExceptionDebugMode";
254       default:
255         MOZ_CRASH("Invalid BailoutKind");
256     }
257 }
258 
259 static const uint32_t ELEMENT_TYPE_BITS = 5;
260 static const uint32_t ELEMENT_TYPE_SHIFT = 0;
261 static const uint32_t ELEMENT_TYPE_MASK = (1 << ELEMENT_TYPE_BITS) - 1;
262 static const uint32_t VECTOR_SCALE_BITS = 2;
263 static const uint32_t VECTOR_SCALE_SHIFT = ELEMENT_TYPE_BITS + ELEMENT_TYPE_SHIFT;
264 static const uint32_t VECTOR_SCALE_MASK = (1 << VECTOR_SCALE_BITS) - 1;
265 
266 class SimdConstant {
267   public:
268     enum Type {
269         Int32x4,
270         Float32x4,
271         Undefined = -1
272     };
273 
274     typedef int32_t I32x4[4];
275     typedef float F32x4[4];
276 
277   private:
278     Type type_;
279     union {
280         I32x4 i32x4;
281         F32x4 f32x4;
282     } u;
283 
defined()284     bool defined() const {
285         return type_ != Undefined;
286     }
287 
fillInt32x4(int32_t x,int32_t y,int32_t z,int32_t w)288     void fillInt32x4(int32_t x, int32_t y, int32_t z, int32_t w)
289     {
290         type_ = Int32x4;
291         u.i32x4[0] = x;
292         u.i32x4[1] = y;
293         u.i32x4[2] = z;
294         u.i32x4[3] = w;
295     }
296 
fillFloat32x4(float x,float y,float z,float w)297     void fillFloat32x4(float x, float y, float z, float w)
298     {
299         type_ = Float32x4;
300         u.f32x4[0] = x;
301         u.f32x4[1] = y;
302         u.f32x4[2] = z;
303         u.f32x4[3] = w;
304     }
305 
306   public:
307     // Doesn't have a default constructor, as it would prevent it from being
308     // included in unions.
309 
CreateX4(int32_t x,int32_t y,int32_t z,int32_t w)310     static SimdConstant CreateX4(int32_t x, int32_t y, int32_t z, int32_t w) {
311         SimdConstant cst;
312         cst.fillInt32x4(x, y, z, w);
313         return cst;
314     }
CreateX4(const int32_t * array)315     static SimdConstant CreateX4(const int32_t* array) {
316         SimdConstant cst;
317         cst.fillInt32x4(array[0], array[1], array[2], array[3]);
318         return cst;
319     }
SplatX4(int32_t v)320     static SimdConstant SplatX4(int32_t v) {
321         SimdConstant cst;
322         cst.fillInt32x4(v, v, v, v);
323         return cst;
324     }
CreateX4(float x,float y,float z,float w)325     static SimdConstant CreateX4(float x, float y, float z, float w) {
326         SimdConstant cst;
327         cst.fillFloat32x4(x, y, z, w);
328         return cst;
329     }
CreateX4(const float * array)330     static SimdConstant CreateX4(const float* array) {
331         SimdConstant cst;
332         cst.fillFloat32x4(array[0], array[1], array[2], array[3]);
333         return cst;
334     }
SplatX4(float v)335     static SimdConstant SplatX4(float v) {
336         SimdConstant cst;
337         cst.fillFloat32x4(v, v, v, v);
338         return cst;
339     }
340 
length()341     uint32_t length() const {
342         MOZ_ASSERT(defined());
343         switch(type_) {
344           case Int32x4:
345           case Float32x4:
346             return 4;
347           case Undefined:
348             break;
349         }
350         MOZ_CRASH("Unexpected SIMD kind");
351     }
352 
type()353     Type type() const {
354         MOZ_ASSERT(defined());
355         return type_;
356     }
357 
asInt32x4()358     const I32x4& asInt32x4() const {
359         MOZ_ASSERT(defined() && type_ == Int32x4);
360         return u.i32x4;
361     }
362 
asFloat32x4()363     const F32x4& asFloat32x4() const {
364         MOZ_ASSERT(defined() && type_ == Float32x4);
365         return u.f32x4;
366     }
367 
368     bool operator==(const SimdConstant& rhs) const {
369         MOZ_ASSERT(defined() && rhs.defined());
370         if (type() != rhs.type())
371             return false;
372         return memcmp(&u, &rhs.u, sizeof(u)) == 0;
373     }
374 
375     // SimdConstant is a HashPolicy
376     typedef SimdConstant Lookup;
hash(const SimdConstant & val)377     static HashNumber hash(const SimdConstant& val) {
378         uint32_t hash = mozilla::HashBytes(&val.u, sizeof(val.u));
379         return mozilla::AddToHash(hash, val.type_);
380     }
match(const SimdConstant & lhs,const SimdConstant & rhs)381     static bool match(const SimdConstant& lhs, const SimdConstant& rhs) {
382         return lhs == rhs;
383     }
384 };
385 
386 // The ordering of this enumeration is important: Anything < Value is a
387 // specialized type. Furthermore, anything < String has trivial conversion to
388 // a number.
389 enum MIRType
390 {
391     MIRType_Undefined,
392     MIRType_Null,
393     MIRType_Boolean,
394     MIRType_Int32,
395     MIRType_Double,
396     MIRType_Float32,
397     MIRType_String,
398     MIRType_Symbol,
399     MIRType_Object,
400     MIRType_MagicOptimizedArguments,   // JS_OPTIMIZED_ARGUMENTS magic value.
401     MIRType_MagicOptimizedOut,         // JS_OPTIMIZED_OUT magic value.
402     MIRType_MagicHole,                 // JS_ELEMENTS_HOLE magic value.
403     MIRType_MagicIsConstructing,       // JS_IS_CONSTRUCTING magic value.
404     MIRType_MagicUninitializedLexical, // JS_UNINITIALIZED_LEXICAL magic value.
405     MIRType_Value,
406     MIRType_SinCosDouble,              // Optimizing a sin/cos to sincos.
407     MIRType_ObjectOrNull,
408     MIRType_None,                      // Invalid, used as a placeholder.
409     MIRType_Slots,                     // A slots vector
410     MIRType_Elements,                  // An elements vector
411     MIRType_Pointer,                   // An opaque pointer that receives no special treatment
412     MIRType_Shape,                     // A Shape pointer.
413     MIRType_ObjectGroup,               // An ObjectGroup pointer.
414     MIRType_Last = MIRType_ObjectGroup,
415     MIRType_Float32x4 = MIRType_Float32 | (2 << VECTOR_SCALE_SHIFT),
416     MIRType_Int32x4   = MIRType_Int32   | (2 << VECTOR_SCALE_SHIFT),
417     MIRType_Doublex2  = MIRType_Double  | (1 << VECTOR_SCALE_SHIFT)
418 };
419 
420 static inline MIRType
MIRTypeFromValueType(JSValueType type)421 MIRTypeFromValueType(JSValueType type)
422 {
423     // This function does not deal with magic types. Magic constants should be
424     // filtered out in MIRTypeFromValue.
425     switch (type) {
426       case JSVAL_TYPE_DOUBLE:
427         return MIRType_Double;
428       case JSVAL_TYPE_INT32:
429         return MIRType_Int32;
430       case JSVAL_TYPE_UNDEFINED:
431         return MIRType_Undefined;
432       case JSVAL_TYPE_STRING:
433         return MIRType_String;
434       case JSVAL_TYPE_SYMBOL:
435         return MIRType_Symbol;
436       case JSVAL_TYPE_BOOLEAN:
437         return MIRType_Boolean;
438       case JSVAL_TYPE_NULL:
439         return MIRType_Null;
440       case JSVAL_TYPE_OBJECT:
441         return MIRType_Object;
442       case JSVAL_TYPE_UNKNOWN:
443         return MIRType_Value;
444       default:
445         MOZ_CRASH("unexpected jsval type");
446     }
447 }
448 
449 static inline JSValueType
ValueTypeFromMIRType(MIRType type)450 ValueTypeFromMIRType(MIRType type)
451 {
452   switch (type) {
453     case MIRType_Undefined:
454       return JSVAL_TYPE_UNDEFINED;
455     case MIRType_Null:
456       return JSVAL_TYPE_NULL;
457     case MIRType_Boolean:
458       return JSVAL_TYPE_BOOLEAN;
459     case MIRType_Int32:
460       return JSVAL_TYPE_INT32;
461     case MIRType_Float32: // Fall through, there's no JSVAL for Float32
462     case MIRType_Double:
463       return JSVAL_TYPE_DOUBLE;
464     case MIRType_String:
465       return JSVAL_TYPE_STRING;
466     case MIRType_Symbol:
467       return JSVAL_TYPE_SYMBOL;
468     case MIRType_MagicOptimizedArguments:
469     case MIRType_MagicOptimizedOut:
470     case MIRType_MagicHole:
471     case MIRType_MagicIsConstructing:
472     case MIRType_MagicUninitializedLexical:
473       return JSVAL_TYPE_MAGIC;
474     default:
475       MOZ_ASSERT(type == MIRType_Object);
476       return JSVAL_TYPE_OBJECT;
477   }
478 }
479 
480 static inline JSValueTag
MIRTypeToTag(MIRType type)481 MIRTypeToTag(MIRType type)
482 {
483     return JSVAL_TYPE_TO_TAG(ValueTypeFromMIRType(type));
484 }
485 
486 static inline const char*
StringFromMIRType(MIRType type)487 StringFromMIRType(MIRType type)
488 {
489   switch (type) {
490     case MIRType_Undefined:
491       return "Undefined";
492     case MIRType_Null:
493       return "Null";
494     case MIRType_Boolean:
495       return "Bool";
496     case MIRType_Int32:
497       return "Int32";
498     case MIRType_Double:
499       return "Double";
500     case MIRType_Float32:
501       return "Float32";
502     case MIRType_String:
503       return "String";
504     case MIRType_Symbol:
505       return "Symbol";
506     case MIRType_Object:
507       return "Object";
508     case MIRType_MagicOptimizedArguments:
509       return "MagicOptimizedArguments";
510     case MIRType_MagicOptimizedOut:
511       return "MagicOptimizedOut";
512     case MIRType_MagicHole:
513       return "MagicHole";
514     case MIRType_MagicIsConstructing:
515       return "MagicIsConstructing";
516     case MIRType_MagicUninitializedLexical:
517       return "MagicUninitializedLexical";
518     case MIRType_Value:
519       return "Value";
520     case MIRType_SinCosDouble:
521       return "SinCosDouble";
522     case MIRType_ObjectOrNull:
523       return "ObjectOrNull";
524     case MIRType_None:
525       return "None";
526     case MIRType_Slots:
527       return "Slots";
528     case MIRType_Elements:
529       return "Elements";
530     case MIRType_Pointer:
531       return "Pointer";
532     case MIRType_Shape:
533       return "Shape";
534     case MIRType_ObjectGroup:
535       return "ObjectGroup";
536     case MIRType_Float32x4:
537       return "Float32x4";
538     case MIRType_Int32x4:
539       return "Int32x4";
540     case MIRType_Doublex2:
541       return "Doublex2";
542     default:
543       MOZ_CRASH("Unknown MIRType.");
544   }
545 }
546 
547 static inline bool
IsNumberType(MIRType type)548 IsNumberType(MIRType type)
549 {
550     return type == MIRType_Int32 || type == MIRType_Double || type == MIRType_Float32;
551 }
552 
553 static inline bool
IsFloatType(MIRType type)554 IsFloatType(MIRType type)
555 {
556     return type == MIRType_Int32 || type == MIRType_Float32;
557 }
558 
559 static inline bool
IsFloatingPointType(MIRType type)560 IsFloatingPointType(MIRType type)
561 {
562     return type == MIRType_Double || type == MIRType_Float32;
563 }
564 
565 static inline bool
IsNullOrUndefined(MIRType type)566 IsNullOrUndefined(MIRType type)
567 {
568     return type == MIRType_Null || type == MIRType_Undefined;
569 }
570 
571 static inline bool
IsSimdType(MIRType type)572 IsSimdType(MIRType type)
573 {
574     return type == MIRType_Int32x4 || type == MIRType_Float32x4;
575 }
576 
577 static inline bool
IsFloatingPointSimdType(MIRType type)578 IsFloatingPointSimdType(MIRType type)
579 {
580     return type == MIRType_Float32x4;
581 }
582 
583 static inline bool
IsIntegerSimdType(MIRType type)584 IsIntegerSimdType(MIRType type)
585 {
586     return type == MIRType_Int32x4;
587 }
588 
589 static inline bool
IsMagicType(MIRType type)590 IsMagicType(MIRType type)
591 {
592     return type == MIRType_MagicHole ||
593            type == MIRType_MagicOptimizedOut ||
594            type == MIRType_MagicIsConstructing ||
595            type == MIRType_MagicOptimizedArguments ||
596            type == MIRType_MagicUninitializedLexical;
597 }
598 
599 // Returns the number of vector elements (hereby called "length") for a given
600 // SIMD kind. It is the Y part of the name "Foo x Y".
601 static inline unsigned
SimdTypeToLength(MIRType type)602 SimdTypeToLength(MIRType type)
603 {
604     MOZ_ASSERT(IsSimdType(type));
605     return 1 << ((type >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK);
606 }
607 
608 static inline MIRType
ScalarTypeToMIRType(Scalar::Type type)609 ScalarTypeToMIRType(Scalar::Type type)
610 {
611     switch (type) {
612       case Scalar::Int8:
613       case Scalar::Uint8:
614       case Scalar::Int16:
615       case Scalar::Uint16:
616       case Scalar::Int32:
617       case Scalar::Uint32:
618       case Scalar::Uint8Clamped:
619         return MIRType_Int32;
620       case Scalar::Float32:
621         return MIRType_Float32;
622       case Scalar::Float64:
623         return MIRType_Double;
624       case Scalar::Float32x4:
625         return MIRType_Float32x4;
626       case Scalar::Int32x4:
627         return MIRType_Int32x4;
628       case Scalar::MaxTypedArrayViewType:
629         break;
630     }
631     MOZ_CRASH("unexpected SIMD kind");
632 }
633 
634 static inline unsigned
ScalarTypeToLength(Scalar::Type type)635 ScalarTypeToLength(Scalar::Type type)
636 {
637     switch (type) {
638       case Scalar::Int8:
639       case Scalar::Uint8:
640       case Scalar::Int16:
641       case Scalar::Uint16:
642       case Scalar::Int32:
643       case Scalar::Uint32:
644       case Scalar::Float32:
645       case Scalar::Float64:
646       case Scalar::Uint8Clamped:
647         return 1;
648       case Scalar::Float32x4:
649       case Scalar::Int32x4:
650         return 4;
651       case Scalar::MaxTypedArrayViewType:
652         break;
653     }
654     MOZ_CRASH("unexpected SIMD kind");
655 }
656 
657 // Get the type of the individual lanes in a SIMD type.
658 // For example, Int32x4 -> Int32, FLoat32x4 -> Float32 etc.
659 static inline MIRType
SimdTypeToLaneType(MIRType type)660 SimdTypeToLaneType(MIRType type)
661 {
662     MOZ_ASSERT(IsSimdType(type));
663     static_assert(MIRType_Last <= ELEMENT_TYPE_MASK,
664                   "ELEMENT_TYPE_MASK should be larger than the last MIRType");
665     return MIRType((type >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK);
666 }
667 
668 // Indicates a lane in a SIMD register: X for the first lane, Y for the second,
669 // Z for the third (if any), W for the fourth (if any).
670 enum SimdLane {
671     LaneX = 0x0,
672     LaneY = 0x1,
673     LaneZ = 0x2,
674     LaneW = 0x3
675 };
676 
677 #ifdef DEBUG
678 
679 // Track the pipeline of opcodes which has produced a snapshot.
680 #define TRACK_SNAPSHOTS 1
681 
682 // Make sure registers are not modified between an instruction and
683 // its OsiPoint.
684 #define CHECK_OSIPOINT_REGISTERS 1
685 
686 #endif // DEBUG
687 
688 enum {
689     ArgType_General = 0x1,
690     ArgType_Double  = 0x2,
691     ArgType_Float32 = 0x3,
692 
693     RetType_Shift   = 0x0,
694     ArgType_Shift   = 0x2,
695     ArgType_Mask    = 0x3
696 };
697 
698 enum ABIFunctionType
699 {
700     // VM functions that take 0-9 non-double arguments
701     // and return a non-double value.
702     Args_General0 = ArgType_General << RetType_Shift,
703     Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
704     Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
705     Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
706     Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
707     Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
708     Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
709     Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
710     Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
711 
712     // double f()
713     Args_Double_None = ArgType_Double << RetType_Shift,
714 
715     // int f(double)
716     Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift),
717 
718     // float f(float)
719     Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
720 
721     // double f(double)
722     Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
723 
724     // double f(int)
725     Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
726 
727     // double f(double, int)
728     Args_Double_DoubleInt = Args_Double_None |
729         (ArgType_General << (ArgType_Shift * 1)) |
730         (ArgType_Double << (ArgType_Shift * 2)),
731 
732     // double f(double, double)
733     Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
734 
735     // double f(int, double)
736     Args_Double_IntDouble = Args_Double_None |
737         (ArgType_Double << (ArgType_Shift * 1)) |
738         (ArgType_General << (ArgType_Shift * 2)),
739 
740     // int f(int, double)
741     Args_Int_IntDouble = Args_General0 |
742         (ArgType_Double << (ArgType_Shift * 1)) |
743         (ArgType_General << (ArgType_Shift * 2)),
744 
745     // double f(double, double, double)
746     Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
747 
748     // double f(double, double, double, double)
749     Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4)),
750 
751     // int f(double, int, int)
752     Args_Int_DoubleIntInt = Args_General0 |
753        (ArgType_General << (ArgType_Shift * 1)) |
754        (ArgType_General << (ArgType_Shift * 2)) |
755        (ArgType_Double  << (ArgType_Shift * 3)),
756 
757     // int f(int, double, int, int)
758     Args_Int_IntDoubleIntInt = Args_General0 |
759         (ArgType_General << (ArgType_Shift * 1)) |
760         (ArgType_General << (ArgType_Shift * 2)) |
761         (ArgType_Double  << (ArgType_Shift * 3)) |
762         (ArgType_General << (ArgType_Shift * 4))
763 
764 };
765 
766 enum class BarrierKind : uint32_t {
767     // No barrier is needed.
768     NoBarrier,
769 
770     // The barrier only has to check the value's type tag is in the TypeSet.
771     // Specific object types don't have to be checked.
772     TypeTagOnly,
773 
774     // Check if the value is in the TypeSet, including the object type if it's
775     // an object.
776     TypeSet
777 };
778 
779 } // namespace jit
780 } // namespace js
781 
782 #endif /* jit_IonTypes_h */
783