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 */
|