michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_IonTypes_h michael@0: #define jit_IonTypes_h michael@0: michael@0: #include "jstypes.h" michael@0: michael@0: #include "js/Value.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: typedef uint32_t RecoverOffset; michael@0: typedef uint32_t SnapshotOffset; michael@0: typedef uint32_t BailoutId; michael@0: michael@0: // The maximum size of any buffer associated with an assembler or code object. michael@0: // This is chosen to not overflow a signed integer, leaving room for an extra michael@0: // bit on offsets. michael@0: static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1; michael@0: michael@0: // Maximum number of scripted arg slots. michael@0: static const uint32_t SNAPSHOT_MAX_NARGS = 127; michael@0: michael@0: static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1); michael@0: static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1); michael@0: michael@0: // Different kinds of bailouts. When extending this enum, make sure to check michael@0: // the bits reserved for bailout kinds in Bailouts.h michael@0: enum BailoutKind michael@0: { michael@0: // A normal bailout triggered from type, shape, and assorted overflow michael@0: // guards in the compiler. michael@0: Bailout_Normal, michael@0: michael@0: // A bailout at the very start of a function indicates that there may be michael@0: // a type mismatch in the arguments that necessitates a reflow. michael@0: Bailout_ArgumentCheck, michael@0: michael@0: // A bailout triggered by a bounds-check failure. michael@0: Bailout_BoundsCheck, michael@0: michael@0: // A shape guard based on TI information failed. michael@0: Bailout_ShapeGuard, michael@0: michael@0: // A bailout caused by invalid assumptions based on Baseline code. michael@0: Bailout_BaselineInfo, michael@0: michael@0: // A bailout to baseline from Ion on exception to handle Debugger hooks. michael@0: Bailout_IonExceptionDebugMode, michael@0: }; michael@0: michael@0: inline const char * michael@0: BailoutKindString(BailoutKind kind) michael@0: { michael@0: switch (kind) { michael@0: case Bailout_Normal: michael@0: return "Bailout_Normal"; michael@0: case Bailout_ArgumentCheck: michael@0: return "Bailout_ArgumentCheck"; michael@0: case Bailout_BoundsCheck: michael@0: return "Bailout_BoundsCheck"; michael@0: case Bailout_ShapeGuard: michael@0: return "Bailout_ShapeGuard"; michael@0: case Bailout_BaselineInfo: michael@0: return "Bailout_BaselineInfo"; michael@0: case Bailout_IonExceptionDebugMode: michael@0: return "Bailout_IonExceptionDebugMode"; michael@0: default: michael@0: MOZ_ASSUME_UNREACHABLE("Invalid BailoutKind"); michael@0: } michael@0: } michael@0: michael@0: static const uint32_t ELEMENT_TYPE_BITS = 5; michael@0: static const uint32_t ELEMENT_TYPE_SHIFT = 0; michael@0: static const uint32_t ELEMENT_TYPE_MASK = (1 << ELEMENT_TYPE_BITS) - 1; michael@0: static const uint32_t VECTOR_SCALE_BITS = 2; michael@0: static const uint32_t VECTOR_SCALE_SHIFT = ELEMENT_TYPE_BITS + ELEMENT_TYPE_SHIFT; michael@0: static const uint32_t VECTOR_SCALE_MASK = (1 << VECTOR_SCALE_BITS) - 1; michael@0: michael@0: // The ordering of this enumeration is important: Anything < Value is a michael@0: // specialized type. Furthermore, anything < String has trivial conversion to michael@0: // a number. michael@0: enum MIRType michael@0: { michael@0: MIRType_Undefined, michael@0: MIRType_Null, michael@0: MIRType_Boolean, michael@0: MIRType_Int32, michael@0: MIRType_Double, michael@0: MIRType_Float32, michael@0: MIRType_String, michael@0: MIRType_Object, michael@0: MIRType_MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value. michael@0: MIRType_MagicOptimizedOut, // JS_OPTIMIZED_OUT magic value. michael@0: MIRType_MagicHole, // JS_ELEMENTS_HOLE magic value. michael@0: MIRType_MagicIsConstructing, // JS_IS_CONSTRUCTING magic value. michael@0: MIRType_Value, michael@0: MIRType_None, // Invalid, used as a placeholder. michael@0: MIRType_Slots, // A slots vector michael@0: MIRType_Elements, // An elements vector michael@0: MIRType_Pointer, // An opaque pointer that receives no special treatment michael@0: MIRType_Shape, // A Shape pointer. michael@0: MIRType_ForkJoinContext, // js::ForkJoinContext* michael@0: MIRType_Last = MIRType_ForkJoinContext, michael@0: MIRType_Float32x4 = MIRType_Float32 | (2 << VECTOR_SCALE_SHIFT), michael@0: MIRType_Int32x4 = MIRType_Int32 | (2 << VECTOR_SCALE_SHIFT), michael@0: MIRType_Doublex2 = MIRType_Double | (1 << VECTOR_SCALE_SHIFT) michael@0: }; michael@0: michael@0: static inline MIRType michael@0: ElementType(MIRType type) michael@0: { michael@0: JS_STATIC_ASSERT(MIRType_Last <= ELEMENT_TYPE_MASK); michael@0: return static_cast((type >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK); michael@0: } michael@0: michael@0: static inline uint32_t michael@0: VectorSize(MIRType type) michael@0: { michael@0: return 1 << ((type >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK); michael@0: } michael@0: michael@0: static inline MIRType michael@0: MIRTypeFromValueType(JSValueType type) michael@0: { michael@0: // This function does not deal with magic types. Magic constants should be michael@0: // filtered out in MIRTypeFromValue. michael@0: switch (type) { michael@0: case JSVAL_TYPE_DOUBLE: michael@0: return MIRType_Double; michael@0: case JSVAL_TYPE_INT32: michael@0: return MIRType_Int32; michael@0: case JSVAL_TYPE_UNDEFINED: michael@0: return MIRType_Undefined; michael@0: case JSVAL_TYPE_STRING: michael@0: return MIRType_String; michael@0: case JSVAL_TYPE_BOOLEAN: michael@0: return MIRType_Boolean; michael@0: case JSVAL_TYPE_NULL: michael@0: return MIRType_Null; michael@0: case JSVAL_TYPE_OBJECT: michael@0: return MIRType_Object; michael@0: case JSVAL_TYPE_UNKNOWN: michael@0: return MIRType_Value; michael@0: default: michael@0: MOZ_ASSUME_UNREACHABLE("unexpected jsval type"); michael@0: } michael@0: } michael@0: michael@0: static inline JSValueType michael@0: ValueTypeFromMIRType(MIRType type) michael@0: { michael@0: switch (type) { michael@0: case MIRType_Undefined: michael@0: return JSVAL_TYPE_UNDEFINED; michael@0: case MIRType_Null: michael@0: return JSVAL_TYPE_NULL; michael@0: case MIRType_Boolean: michael@0: return JSVAL_TYPE_BOOLEAN; michael@0: case MIRType_Int32: michael@0: return JSVAL_TYPE_INT32; michael@0: case MIRType_Float32: // Fall through, there's no JSVAL for Float32 michael@0: case MIRType_Double: michael@0: return JSVAL_TYPE_DOUBLE; michael@0: case MIRType_String: michael@0: return JSVAL_TYPE_STRING; michael@0: case MIRType_MagicOptimizedArguments: michael@0: case MIRType_MagicOptimizedOut: michael@0: case MIRType_MagicHole: michael@0: case MIRType_MagicIsConstructing: michael@0: return JSVAL_TYPE_MAGIC; michael@0: default: michael@0: JS_ASSERT(type == MIRType_Object); michael@0: return JSVAL_TYPE_OBJECT; michael@0: } michael@0: } michael@0: michael@0: static inline JSValueTag michael@0: MIRTypeToTag(MIRType type) michael@0: { michael@0: return JSVAL_TYPE_TO_TAG(ValueTypeFromMIRType(type)); michael@0: } michael@0: michael@0: static inline const char * michael@0: StringFromMIRType(MIRType type) michael@0: { michael@0: switch (type) { michael@0: case MIRType_Undefined: michael@0: return "Undefined"; michael@0: case MIRType_Null: michael@0: return "Null"; michael@0: case MIRType_Boolean: michael@0: return "Bool"; michael@0: case MIRType_Int32: michael@0: return "Int32"; michael@0: case MIRType_Double: michael@0: return "Double"; michael@0: case MIRType_Float32: michael@0: return "Float32"; michael@0: case MIRType_String: michael@0: return "String"; michael@0: case MIRType_Object: michael@0: return "Object"; michael@0: case MIRType_MagicOptimizedArguments: michael@0: return "MagicOptimizedArguments"; michael@0: case MIRType_MagicOptimizedOut: michael@0: return "MagicOptimizedOut"; michael@0: case MIRType_MagicHole: michael@0: return "MagicHole"; michael@0: case MIRType_MagicIsConstructing: michael@0: return "MagicIsConstructing"; michael@0: case MIRType_Value: michael@0: return "Value"; michael@0: case MIRType_None: michael@0: return "None"; michael@0: case MIRType_Slots: michael@0: return "Slots"; michael@0: case MIRType_Elements: michael@0: return "Elements"; michael@0: case MIRType_Pointer: michael@0: return "Pointer"; michael@0: case MIRType_ForkJoinContext: michael@0: return "ForkJoinContext"; michael@0: default: michael@0: MOZ_ASSUME_UNREACHABLE("Unknown MIRType."); michael@0: } michael@0: } michael@0: michael@0: static inline bool michael@0: IsNumberType(MIRType type) michael@0: { michael@0: return type == MIRType_Int32 || type == MIRType_Double || type == MIRType_Float32; michael@0: } michael@0: michael@0: static inline bool michael@0: IsFloatType(MIRType type) michael@0: { michael@0: return type == MIRType_Int32 || type == MIRType_Float32; michael@0: } michael@0: michael@0: static inline bool michael@0: IsFloatingPointType(MIRType type) michael@0: { michael@0: return type == MIRType_Double || type == MIRType_Float32; michael@0: } michael@0: michael@0: static inline bool michael@0: IsNullOrUndefined(MIRType type) michael@0: { michael@0: return type == MIRType_Null || type == MIRType_Undefined; michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: // Track the pipeline of opcodes which has produced a snapshot. michael@0: #define TRACK_SNAPSHOTS 1 michael@0: michael@0: // Make sure registers are not modified between an instruction and michael@0: // its OsiPoint. michael@0: # if defined(JS_ION) michael@0: # define CHECK_OSIPOINT_REGISTERS 1 michael@0: # endif michael@0: #endif michael@0: michael@0: enum { michael@0: ArgType_General = 0x1, michael@0: ArgType_Double = 0x2, michael@0: ArgType_Float32 = 0x3, michael@0: michael@0: RetType_Shift = 0x0, michael@0: ArgType_Shift = 0x2, michael@0: ArgType_Mask = 0x3 michael@0: }; michael@0: michael@0: enum ABIFunctionType michael@0: { michael@0: // VM functions that take 0-9 non-double arguments michael@0: // and return a non-double value. michael@0: Args_General0 = ArgType_General << RetType_Shift, michael@0: Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)), michael@0: Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)), michael@0: Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)), michael@0: Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)), michael@0: Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)), michael@0: Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)), michael@0: Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)), michael@0: Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)), michael@0: michael@0: // double f() michael@0: Args_Double_None = ArgType_Double << RetType_Shift, michael@0: michael@0: // int f(double) michael@0: Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift), michael@0: michael@0: // float f(float) michael@0: Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift), michael@0: michael@0: // double f(double) michael@0: Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift), michael@0: michael@0: // double f(int) michael@0: Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift), michael@0: michael@0: // double f(double, int) michael@0: Args_Double_DoubleInt = Args_Double_None | michael@0: (ArgType_General << (ArgType_Shift * 1)) | michael@0: (ArgType_Double << (ArgType_Shift * 2)), michael@0: michael@0: // double f(double, double) michael@0: Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)), michael@0: michael@0: // double f(int, double) michael@0: Args_Double_IntDouble = Args_Double_None | michael@0: (ArgType_Double << (ArgType_Shift * 1)) | michael@0: (ArgType_General << (ArgType_Shift * 2)), michael@0: michael@0: // int f(int, double) michael@0: Args_Int_IntDouble = Args_General0 | michael@0: (ArgType_Double << (ArgType_Shift * 1)) | michael@0: (ArgType_General << (ArgType_Shift * 2)) michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_IonTypes_h */