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