blob: 8030f1609f7c0bc1a3055ae4dd46c0847a66f19d [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_IonTypes_h
#define jit_IonTypes_h
#include "mozilla/HashFunctions.h"
#include "jsfriendapi.h"
#include "jstypes.h"
#include "js/Value.h"
namespace js {
namespace jit {
typedef uint32_t RecoverOffset;
typedef uint32_t SnapshotOffset;
typedef uint32_t BailoutId;
// The maximum size of any buffer associated with an assembler or code object.
// This is chosen to not overflow a signed integer, leaving room for an extra
// bit on offsets.
static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
// Maximum number of scripted arg slots.
static const uint32_t SNAPSHOT_MAX_NARGS = 127;
static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
// Different kinds of bailouts. When extending this enum, make sure to check
// the bits reserved for bailout kinds in Bailouts.h
enum BailoutKind
{
// Normal bailouts, that don't need to be handled specially when restarting
// in baseline.
// An inevitable bailout (MBail instruction or type barrier that always bails)
Bailout_Inevitable,
// Bailing out during a VM call. Many possible causes that are hard
// to distinguish statically at snapshot construction time.
// We just lump them together.
Bailout_DuringVMCall,
// Call to a non-JSFunction (problem for |apply|)
Bailout_NonJSFunctionCallee,
// Dynamic scope chain lookup produced |undefined|
Bailout_DynamicNameNotFound,
// Input string contains 'arguments' or 'eval'
Bailout_StringArgumentsEval,
// Bailout on overflow, but don't immediately invalidate.
// Used for abs, sub and LoadUnboxedScalar (when loading a uint32 that
// doesn't fit in an int32).
Bailout_Overflow,
// floor, ceiling and round bail if input is NaN, if output would be -0 or
// doesn't fit in int32 range
Bailout_Round,
// Non-primitive value used as input for ToDouble, ToInt32, ToString, etc.
// For ToInt32, can also mean that input can't be converted without precision
// loss (e.g. 5.5).
Bailout_NonPrimitiveInput,
// For ToInt32, would lose precision when converting (e.g. 5.5).
Bailout_PrecisionLoss,
// We tripped a type barrier (object was not in the expected TypeSet)
Bailout_TypeBarrierO,
// We tripped a type barrier (value was not in the expected TypeSet)
Bailout_TypeBarrierV,
// We tripped a type monitor (wrote an unexpected type in a property)
Bailout_MonitorTypes,
// We hit a hole in an array.
Bailout_Hole,
// Array access with negative index
Bailout_NegativeIndex,
// Pretty specific case:
// - need a type barrier on a property write
// - all but one of the observed types have property types that reflect the value
// - we need to guard that we're not given an object of that one other type
// also used for the unused GuardClass instruction
Bailout_ObjectIdentityOrTypeGuard,
// Unbox expects a given type, bails out if it doesn't get it.
Bailout_NonInt32Input,
Bailout_NonNumericInput, // unboxing a double works with int32 too
Bailout_NonBooleanInput,
Bailout_NonObjectInput,
Bailout_NonStringInput,
Bailout_NonSymbolInput,
// SIMD Unbox expects a given type, bails out if it doesn't match.
Bailout_NonSimdInt32x4Input,
Bailout_NonSimdFloat32x4Input,
// Atomic operations require shared memory, bail out if the typed array
// maps unshared memory.
Bailout_NonSharedTypedArrayInput,
// For the initial snapshot when entering a function.
Bailout_InitialState,
// We hit a |debugger;| statement.
Bailout_Debugger,
// |this| used uninitialized in a derived constructor
Bailout_UninitializedThis,
// Derived constructors must return object or undefined
Bailout_BadDerivedConstructorReturn,
// We hit this code for the first time.
Bailout_FirstExecution,
// END Normal bailouts
// Bailouts caused by invalid assumptions based on Baseline code.
// Causes immediate invalidation.
// Like Bailout_Overflow, but causes immediate invalidation.
Bailout_OverflowInvalidate,
// Like NonStringInput, but should cause immediate invalidation.
// Used for jsop_iternext.
Bailout_NonStringInputInvalidate,
// Used for integer division, multiplication and modulo.
// If there's a remainder, bails to return a double.
// Can also signal overflow or result of -0.
// Can also signal division by 0 (returns inf, a double).
Bailout_DoubleOutput,
// END Invalid assumptions bailouts
// A bailout at the very start of a function indicates that there may be
// a type mismatch in the arguments that necessitates a reflow.
Bailout_ArgumentCheck,
// A bailout triggered by a bounds-check failure.
Bailout_BoundsCheck,
// A bailout triggered by a neutered typed object.
Bailout_Neutered,
// A shape guard based on TI information failed.
// (We saw an object whose shape does not match that / any of those observed
// by the baseline IC.)
Bailout_ShapeGuard,
// When we're trying to use an uninitialized lexical.
Bailout_UninitializedLexical,
// A bailout to baseline from Ion on exception to handle Debugger hooks.
Bailout_IonExceptionDebugMode
};
inline const char*
BailoutKindString(BailoutKind kind)
{
switch (kind) {
// Normal bailouts.
case Bailout_Inevitable:
return "Bailout_Inevitable";
case Bailout_DuringVMCall:
return "Bailout_DuringVMCall";
case Bailout_NonJSFunctionCallee:
return "Bailout_NonJSFunctionCallee";
case Bailout_DynamicNameNotFound:
return "Bailout_DynamicNameNotFound";
case Bailout_StringArgumentsEval:
return "Bailout_StringArgumentsEval";
case Bailout_Overflow:
return "Bailout_Overflow";
case Bailout_Round:
return "Bailout_Round";
case Bailout_NonPrimitiveInput:
return "Bailout_NonPrimitiveInput";
case Bailout_PrecisionLoss:
return "Bailout_PrecisionLoss";
case Bailout_TypeBarrierO:
return "Bailout_TypeBarrierO";
case Bailout_TypeBarrierV:
return "Bailout_TypeBarrierV";
case Bailout_MonitorTypes:
return "Bailout_MonitorTypes";
case Bailout_Hole:
return "Bailout_Hole";
case Bailout_NegativeIndex:
return "Bailout_NegativeIndex";
case Bailout_ObjectIdentityOrTypeGuard:
return "Bailout_ObjectIdentityOrTypeGuard";
case Bailout_NonInt32Input:
return "Bailout_NonInt32Input";
case Bailout_NonNumericInput:
return "Bailout_NonNumericInput";
case Bailout_NonBooleanInput:
return "Bailout_NonBooleanInput";
case Bailout_NonObjectInput:
return "Bailout_NonObjectInput";
case Bailout_NonStringInput:
return "Bailout_NonStringInput";
case Bailout_NonSymbolInput:
return "Bailout_NonSymbolInput";
case Bailout_NonSimdInt32x4Input:
return "Bailout_NonSimdInt32x4Input";
case Bailout_NonSimdFloat32x4Input:
return "Bailout_NonSimdFloat32x4Input";
case Bailout_NonSharedTypedArrayInput:
return "Bailout_NonSharedTypedArrayInput";
case Bailout_InitialState:
return "Bailout_InitialState";
case Bailout_Debugger:
return "Bailout_Debugger";
case Bailout_UninitializedThis:
return "Bailout_UninitializedThis";
case Bailout_BadDerivedConstructorReturn:
return "Bailout_BadDerivedConstructorReturn";
case Bailout_FirstExecution:
return "Bailout_FirstExecution";
// Bailouts caused by invalid assumptions.
case Bailout_OverflowInvalidate:
return "Bailout_OverflowInvalidate";
case Bailout_NonStringInputInvalidate:
return "Bailout_NonStringInputInvalidate";
case Bailout_DoubleOutput:
return "Bailout_DoubleOutput";
// Other bailouts.
case Bailout_ArgumentCheck:
return "Bailout_ArgumentCheck";
case Bailout_BoundsCheck:
return "Bailout_BoundsCheck";
case Bailout_Neutered:
return "Bailout_Neutered";
case Bailout_ShapeGuard:
return "Bailout_ShapeGuard";
case Bailout_UninitializedLexical:
return "Bailout_UninitializedLexical";
case Bailout_IonExceptionDebugMode:
return "Bailout_IonExceptionDebugMode";
default:
MOZ_CRASH("Invalid BailoutKind");
}
}
static const uint32_t ELEMENT_TYPE_BITS = 5;
static const uint32_t ELEMENT_TYPE_SHIFT = 0;
static const uint32_t ELEMENT_TYPE_MASK = (1 << ELEMENT_TYPE_BITS) - 1;
static const uint32_t VECTOR_SCALE_BITS = 2;
static const uint32_t VECTOR_SCALE_SHIFT = ELEMENT_TYPE_BITS + ELEMENT_TYPE_SHIFT;
static const uint32_t VECTOR_SCALE_MASK = (1 << VECTOR_SCALE_BITS) - 1;
class SimdConstant {
public:
enum Type {
Int32x4,
Float32x4,
Undefined = -1
};
typedef int32_t I32x4[4];
typedef float F32x4[4];
private:
Type type_;
union {
I32x4 i32x4;
F32x4 f32x4;
} u;
bool defined() const {
return type_ != Undefined;
}
void fillInt32x4(int32_t x, int32_t y, int32_t z, int32_t w)
{
type_ = Int32x4;
u.i32x4[0] = x;
u.i32x4[1] = y;
u.i32x4[2] = z;
u.i32x4[3] = w;
}
void fillFloat32x4(float x, float y, float z, float w)
{
type_ = Float32x4;
u.f32x4[0] = x;
u.f32x4[1] = y;
u.f32x4[2] = z;
u.f32x4[3] = w;
}
public:
// Doesn't have a default constructor, as it would prevent it from being
// included in unions.
static SimdConstant CreateX4(int32_t x, int32_t y, int32_t z, int32_t w) {
SimdConstant cst;
cst.fillInt32x4(x, y, z, w);
return cst;
}
static SimdConstant CreateX4(const int32_t* array) {
SimdConstant cst;
cst.fillInt32x4(array[0], array[1], array[2], array[3]);
return cst;
}
static SimdConstant SplatX4(int32_t v) {
SimdConstant cst;
cst.fillInt32x4(v, v, v, v);
return cst;
}
static SimdConstant CreateX4(float x, float y, float z, float w) {
SimdConstant cst;
cst.fillFloat32x4(x, y, z, w);
return cst;
}
static SimdConstant CreateX4(const float* array) {
SimdConstant cst;
cst.fillFloat32x4(array[0], array[1], array[2], array[3]);
return cst;
}
static SimdConstant SplatX4(float v) {
SimdConstant cst;
cst.fillFloat32x4(v, v, v, v);
return cst;
}
uint32_t length() const {
MOZ_ASSERT(defined());
switch(type_) {
case Int32x4:
case Float32x4:
return 4;
case Undefined:
break;
}
MOZ_CRASH("Unexpected SIMD kind");
}
Type type() const {
MOZ_ASSERT(defined());
return type_;
}
const I32x4& asInt32x4() const {
MOZ_ASSERT(defined() && type_ == Int32x4);
return u.i32x4;
}
const F32x4& asFloat32x4() const {
MOZ_ASSERT(defined() && type_ == Float32x4);
return u.f32x4;
}
bool operator==(const SimdConstant& rhs) const {
MOZ_ASSERT(defined() && rhs.defined());
if (type() != rhs.type())
return false;
return memcmp(&u, &rhs.u, sizeof(u)) == 0;
}
// SimdConstant is a HashPolicy
typedef SimdConstant Lookup;
static HashNumber hash(const SimdConstant& val) {
uint32_t hash = mozilla::HashBytes(&val.u, sizeof(val.u));
return mozilla::AddToHash(hash, val.type_);
}
static bool match(const SimdConstant& lhs, const SimdConstant& rhs) {
return lhs == rhs;
}
};
// The ordering of this enumeration is important: Anything < Value is a
// specialized type. Furthermore, anything < String has trivial conversion to
// a number.
enum MIRType
{
MIRType_Undefined,
MIRType_Null,
MIRType_Boolean,
MIRType_Int32,
MIRType_Double,
MIRType_Float32,
MIRType_String,
MIRType_Symbol,
MIRType_Object,
MIRType_MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value.
MIRType_MagicOptimizedOut, // JS_OPTIMIZED_OUT magic value.
MIRType_MagicHole, // JS_ELEMENTS_HOLE magic value.
MIRType_MagicIsConstructing, // JS_IS_CONSTRUCTING magic value.
MIRType_MagicUninitializedLexical, // JS_UNINITIALIZED_LEXICAL magic value.
MIRType_Value,
MIRType_SinCosDouble, // Optimizing a sin/cos to sincos.
MIRType_ObjectOrNull,
MIRType_None, // Invalid, used as a placeholder.
MIRType_Slots, // A slots vector
MIRType_Elements, // An elements vector
MIRType_Pointer, // An opaque pointer that receives no special treatment
MIRType_Shape, // A Shape pointer.
MIRType_ObjectGroup, // An ObjectGroup pointer.
MIRType_Last = MIRType_ObjectGroup,
MIRType_Float32x4 = MIRType_Float32 | (2 << VECTOR_SCALE_SHIFT),
MIRType_Int32x4 = MIRType_Int32 | (2 << VECTOR_SCALE_SHIFT),
MIRType_Doublex2 = MIRType_Double | (1 << VECTOR_SCALE_SHIFT)
};
static inline MIRType
MIRTypeFromValueType(JSValueType type)
{
// This function does not deal with magic types. Magic constants should be
// filtered out in MIRTypeFromValue.
switch (type) {
case JSVAL_TYPE_DOUBLE:
return MIRType_Double;
case JSVAL_TYPE_INT32:
return MIRType_Int32;
case JSVAL_TYPE_UNDEFINED:
return MIRType_Undefined;
case JSVAL_TYPE_STRING:
return MIRType_String;
case JSVAL_TYPE_SYMBOL:
return MIRType_Symbol;
case JSVAL_TYPE_BOOLEAN:
return MIRType_Boolean;
case JSVAL_TYPE_NULL:
return MIRType_Null;
case JSVAL_TYPE_OBJECT:
return MIRType_Object;
case JSVAL_TYPE_UNKNOWN:
return MIRType_Value;
default:
MOZ_CRASH("unexpected jsval type");
}
}
static inline JSValueType
ValueTypeFromMIRType(MIRType type)
{
switch (type) {
case MIRType_Undefined:
return JSVAL_TYPE_UNDEFINED;
case MIRType_Null:
return JSVAL_TYPE_NULL;
case MIRType_Boolean:
return JSVAL_TYPE_BOOLEAN;
case MIRType_Int32:
return JSVAL_TYPE_INT32;
case MIRType_Float32: // Fall through, there's no JSVAL for Float32
case MIRType_Double:
return JSVAL_TYPE_DOUBLE;
case MIRType_String:
return JSVAL_TYPE_STRING;
case MIRType_Symbol:
return JSVAL_TYPE_SYMBOL;
case MIRType_MagicOptimizedArguments:
case MIRType_MagicOptimizedOut:
case MIRType_MagicHole:
case MIRType_MagicIsConstructing:
case MIRType_MagicUninitializedLexical:
return JSVAL_TYPE_MAGIC;
default:
MOZ_ASSERT(type == MIRType_Object);
return JSVAL_TYPE_OBJECT;
}
}
static inline JSValueTag
MIRTypeToTag(MIRType type)
{
return JSVAL_TYPE_TO_TAG(ValueTypeFromMIRType(type));
}
static inline const char*
StringFromMIRType(MIRType type)
{
switch (type) {
case MIRType_Undefined:
return "Undefined";
case MIRType_Null:
return "Null";
case MIRType_Boolean:
return "Bool";
case MIRType_Int32:
return "Int32";
case MIRType_Double:
return "Double";
case MIRType_Float32:
return "Float32";
case MIRType_String:
return "String";
case MIRType_Symbol:
return "Symbol";
case MIRType_Object:
return "Object";
case MIRType_MagicOptimizedArguments:
return "MagicOptimizedArguments";
case MIRType_MagicOptimizedOut:
return "MagicOptimizedOut";
case MIRType_MagicHole:
return "MagicHole";
case MIRType_MagicIsConstructing:
return "MagicIsConstructing";
case MIRType_MagicUninitializedLexical:
return "MagicUninitializedLexical";
case MIRType_Value:
return "Value";
case MIRType_SinCosDouble:
return "SinCosDouble";
case MIRType_ObjectOrNull:
return "ObjectOrNull";
case MIRType_None:
return "None";
case MIRType_Slots:
return "Slots";
case MIRType_Elements:
return "Elements";
case MIRType_Pointer:
return "Pointer";
case MIRType_Shape:
return "Shape";
case MIRType_ObjectGroup:
return "ObjectGroup";
case MIRType_Float32x4:
return "Float32x4";
case MIRType_Int32x4:
return "Int32x4";
case MIRType_Doublex2:
return "Doublex2";
default:
MOZ_CRASH("Unknown MIRType.");
}
}
static inline bool
IsNumberType(MIRType type)
{
return type == MIRType_Int32 || type == MIRType_Double || type == MIRType_Float32;
}
static inline bool
IsFloatType(MIRType type)
{
return type == MIRType_Int32 || type == MIRType_Float32;
}
static inline bool
IsFloatingPointType(MIRType type)
{
return type == MIRType_Double || type == MIRType_Float32;
}
static inline bool
IsNullOrUndefined(MIRType type)
{
return type == MIRType_Null || type == MIRType_Undefined;
}
static inline bool
IsSimdType(MIRType type)
{
return type == MIRType_Int32x4 || type == MIRType_Float32x4;
}
static inline bool
IsFloatingPointSimdType(MIRType type)
{
return type == MIRType_Float32x4;
}
static inline bool
IsIntegerSimdType(MIRType type)
{
return type == MIRType_Int32x4;
}
static inline bool
IsMagicType(MIRType type)
{
return type == MIRType_MagicHole ||
type == MIRType_MagicOptimizedOut ||
type == MIRType_MagicIsConstructing ||
type == MIRType_MagicOptimizedArguments ||
type == MIRType_MagicUninitializedLexical;
}
// Returns the number of vector elements (hereby called "length") for a given
// SIMD kind. It is the Y part of the name "Foo x Y".
static inline unsigned
SimdTypeToLength(MIRType type)
{
MOZ_ASSERT(IsSimdType(type));
return 1 << ((type >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK);
}
static inline MIRType
ScalarTypeToMIRType(Scalar::Type type)
{
switch (type) {
case Scalar::Int8:
case Scalar::Uint8:
case Scalar::Int16:
case Scalar::Uint16:
case Scalar::Int32:
case Scalar::Uint32:
case Scalar::Uint8Clamped:
return MIRType_Int32;
case Scalar::Float32:
return MIRType_Float32;
case Scalar::Float64:
return MIRType_Double;
case Scalar::Float32x4:
return MIRType_Float32x4;
case Scalar::Int32x4:
return MIRType_Int32x4;
case Scalar::MaxTypedArrayViewType:
break;
}
MOZ_CRASH("unexpected SIMD kind");
}
static inline unsigned
ScalarTypeToLength(Scalar::Type type)
{
switch (type) {
case Scalar::Int8:
case Scalar::Uint8:
case Scalar::Int16:
case Scalar::Uint16:
case Scalar::Int32:
case Scalar::Uint32:
case Scalar::Float32:
case Scalar::Float64:
case Scalar::Uint8Clamped:
return 1;
case Scalar::Float32x4:
case Scalar::Int32x4:
return 4;
case Scalar::MaxTypedArrayViewType:
break;
}
MOZ_CRASH("unexpected SIMD kind");
}
// Get the type of the individual lanes in a SIMD type.
// For example, Int32x4 -> Int32, FLoat32x4 -> Float32 etc.
static inline MIRType
SimdTypeToLaneType(MIRType type)
{
MOZ_ASSERT(IsSimdType(type));
static_assert(MIRType_Last <= ELEMENT_TYPE_MASK,
"ELEMENT_TYPE_MASK should be larger than the last MIRType");
return MIRType((type >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK);
}
// Indicates a lane in a SIMD register: X for the first lane, Y for the second,
// Z for the third (if any), W for the fourth (if any).
enum SimdLane {
LaneX = 0x0,
LaneY = 0x1,
LaneZ = 0x2,
LaneW = 0x3
};
#ifdef DEBUG
// Track the pipeline of opcodes which has produced a snapshot.
#define TRACK_SNAPSHOTS 1
// Make sure registers are not modified between an instruction and
// its OsiPoint.
#define CHECK_OSIPOINT_REGISTERS 1
#endif // DEBUG
enum {
ArgType_General = 0x1,
ArgType_Double = 0x2,
ArgType_Float32 = 0x3,
RetType_Shift = 0x0,
ArgType_Shift = 0x2,
ArgType_Mask = 0x3
};
enum ABIFunctionType
{
// VM functions that take 0-9 non-double arguments
// and return a non-double value.
Args_General0 = ArgType_General << RetType_Shift,
Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
// double f()
Args_Double_None = ArgType_Double << RetType_Shift,
// int f(double)
Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift),
// float f(float)
Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
// double f(double)
Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
// double f(int)
Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
// double f(double, int)
Args_Double_DoubleInt = Args_Double_None |
(ArgType_General << (ArgType_Shift * 1)) |
(ArgType_Double << (ArgType_Shift * 2)),
// double f(double, double)
Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
// double f(int, double)
Args_Double_IntDouble = Args_Double_None |
(ArgType_Double << (ArgType_Shift * 1)) |
(ArgType_General << (ArgType_Shift * 2)),
// int f(int, double)
Args_Int_IntDouble = Args_General0 |
(ArgType_Double << (ArgType_Shift * 1)) |
(ArgType_General << (ArgType_Shift * 2)),
// double f(double, double, double)
Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
// double f(double, double, double, double)
Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4)),
// int f(double, int, int)
Args_Int_DoubleIntInt = Args_General0 |
(ArgType_General << (ArgType_Shift * 1)) |
(ArgType_General << (ArgType_Shift * 2)) |
(ArgType_Double << (ArgType_Shift * 3)),
// int f(int, double, int, int)
Args_Int_IntDoubleIntInt = Args_General0 |
(ArgType_General << (ArgType_Shift * 1)) |
(ArgType_General << (ArgType_Shift * 2)) |
(ArgType_Double << (ArgType_Shift * 3)) |
(ArgType_General << (ArgType_Shift * 4))
};
enum class BarrierKind : uint32_t {
// No barrier is needed.
NoBarrier,
// The barrier only has to check the value's type tag is in the TypeSet.
// Specific object types don't have to be checked.
TypeTagOnly,
// Check if the value is in the TypeSet, including the object type if it's
// an object.
TypeSet
};
} // namespace jit
} // namespace js
#endif /* jit_IonTypes_h */