diff -r 000000000000 -r 6474c204b198 js/src/jit/IonTypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jit/IonTypes.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,330 @@ +/* -*- 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 "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 +{ + // A normal bailout triggered from type, shape, and assorted overflow + // guards in the compiler. + Bailout_Normal, + + // 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 shape guard based on TI information failed. + Bailout_ShapeGuard, + + // A bailout caused by invalid assumptions based on Baseline code. + Bailout_BaselineInfo, + + // A bailout to baseline from Ion on exception to handle Debugger hooks. + Bailout_IonExceptionDebugMode, +}; + +inline const char * +BailoutKindString(BailoutKind kind) +{ + switch (kind) { + case Bailout_Normal: + return "Bailout_Normal"; + case Bailout_ArgumentCheck: + return "Bailout_ArgumentCheck"; + case Bailout_BoundsCheck: + return "Bailout_BoundsCheck"; + case Bailout_ShapeGuard: + return "Bailout_ShapeGuard"; + case Bailout_BaselineInfo: + return "Bailout_BaselineInfo"; + case Bailout_IonExceptionDebugMode: + return "Bailout_IonExceptionDebugMode"; + default: + MOZ_ASSUME_UNREACHABLE("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; + +// 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_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_Value, + 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_ForkJoinContext, // js::ForkJoinContext* + MIRType_Last = MIRType_ForkJoinContext, + 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 +ElementType(MIRType type) +{ + JS_STATIC_ASSERT(MIRType_Last <= ELEMENT_TYPE_MASK); + return static_cast((type >> ELEMENT_TYPE_SHIFT) & ELEMENT_TYPE_MASK); +} + +static inline uint32_t +VectorSize(MIRType type) +{ + return 1 << ((type >> VECTOR_SCALE_SHIFT) & VECTOR_SCALE_MASK); +} + +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_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_ASSUME_UNREACHABLE("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_MagicOptimizedArguments: + case MIRType_MagicOptimizedOut: + case MIRType_MagicHole: + case MIRType_MagicIsConstructing: + return JSVAL_TYPE_MAGIC; + default: + JS_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_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_Value: + return "Value"; + case MIRType_None: + return "None"; + case MIRType_Slots: + return "Slots"; + case MIRType_Elements: + return "Elements"; + case MIRType_Pointer: + return "Pointer"; + case MIRType_ForkJoinContext: + return "ForkJoinContext"; + default: + MOZ_ASSUME_UNREACHABLE("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; +} + +#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. +# if defined(JS_ION) +# define CHECK_OSIPOINT_REGISTERS 1 +# endif +#endif + +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)) +}; + +} // namespace jit +} // namespace js + +#endif /* jit_IonTypes_h */