1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/RangeAnalysis.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,591 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_RangeAnalysis_h 1.11 +#define jit_RangeAnalysis_h 1.12 + 1.13 +#include "mozilla/FloatingPoint.h" 1.14 +#include "mozilla/MathAlgorithms.h" 1.15 + 1.16 +#include "jit/IonAnalysis.h" 1.17 +#include "jit/MIR.h" 1.18 + 1.19 +// windows.h defines those, which messes with the definitions below. 1.20 +#undef min 1.21 +#undef max 1.22 + 1.23 +namespace js { 1.24 +namespace jit { 1.25 + 1.26 +class MBasicBlock; 1.27 +class MIRGraph; 1.28 + 1.29 +// An upper bound computed on the number of backedges a loop will take. 1.30 +// This count only includes backedges taken while running Ion code: for OSR 1.31 +// loops, this will exclude iterations that executed in the interpreter or in 1.32 +// baseline compiled code. 1.33 +struct LoopIterationBound : public TempObject 1.34 +{ 1.35 + // Loop for which this bound applies. 1.36 + MBasicBlock *header; 1.37 + 1.38 + // Test from which this bound was derived. Code in the loop body which this 1.39 + // test dominates (will include the backedge) will execute at most 'bound' 1.40 + // times. Other code in the loop will execute at most '1 + Max(bound, 0)' 1.41 + // times. 1.42 + MTest *test; 1.43 + 1.44 + // Symbolic bound computed for the number of backedge executions. 1.45 + LinearSum sum; 1.46 + 1.47 + LoopIterationBound(MBasicBlock *header, MTest *test, LinearSum sum) 1.48 + : header(header), test(test), sum(sum) 1.49 + { 1.50 + } 1.51 +}; 1.52 + 1.53 +// A symbolic upper or lower bound computed for a term. 1.54 +struct SymbolicBound : public TempObject 1.55 +{ 1.56 + private: 1.57 + SymbolicBound(LoopIterationBound *loop, LinearSum sum) 1.58 + : loop(loop), sum(sum) 1.59 + { 1.60 + } 1.61 + 1.62 + public: 1.63 + // Any loop iteration bound from which this was derived. 1.64 + // 1.65 + // If non-nullptr, then 'sum' is only valid within the loop body, at 1.66 + // points dominated by the loop bound's test (see LoopIterationBound). 1.67 + // 1.68 + // If nullptr, then 'sum' is always valid. 1.69 + LoopIterationBound *loop; 1.70 + 1.71 + static SymbolicBound *New(TempAllocator &alloc, LoopIterationBound *loop, LinearSum sum) { 1.72 + return new(alloc) SymbolicBound(loop, sum); 1.73 + } 1.74 + 1.75 + // Computed symbolic bound, see above. 1.76 + LinearSum sum; 1.77 + 1.78 + void print(Sprinter &sp) const; 1.79 + void dump() const; 1.80 +}; 1.81 + 1.82 +class RangeAnalysis 1.83 +{ 1.84 + protected: 1.85 + bool blockDominates(MBasicBlock *b, MBasicBlock *b2); 1.86 + void replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom, 1.87 + MBasicBlock *block); 1.88 + 1.89 + protected: 1.90 + MIRGenerator *mir; 1.91 + MIRGraph &graph_; 1.92 + 1.93 + TempAllocator &alloc() const; 1.94 + 1.95 + public: 1.96 + MOZ_CONSTEXPR RangeAnalysis(MIRGenerator *mir, MIRGraph &graph) : 1.97 + mir(mir), graph_(graph) {} 1.98 + bool addBetaNodes(); 1.99 + bool analyze(); 1.100 + bool addRangeAssertions(); 1.101 + bool removeBetaNodes(); 1.102 + bool prepareForUCE(bool *shouldRemoveDeadCode); 1.103 + bool truncate(); 1.104 + 1.105 + private: 1.106 + bool analyzeLoop(MBasicBlock *header); 1.107 + LoopIterationBound *analyzeLoopIterationCount(MBasicBlock *header, 1.108 + MTest *test, BranchDirection direction); 1.109 + void analyzeLoopPhi(MBasicBlock *header, LoopIterationBound *loopBound, MPhi *phi); 1.110 + bool tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins); 1.111 + bool markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current); 1.112 +}; 1.113 + 1.114 +class Range : public TempObject { 1.115 + public: 1.116 + // Int32 are signed. INT32_MAX is pow(2,31)-1 and INT32_MIN is -pow(2,31), 1.117 + // so the greatest exponent we need is 31. 1.118 + static const uint16_t MaxInt32Exponent = 31; 1.119 + 1.120 + // UInt32 are unsigned. UINT32_MAX is pow(2,32)-1, so it's the greatest 1.121 + // value that has an exponent of 31. 1.122 + static const uint16_t MaxUInt32Exponent = 31; 1.123 + 1.124 + // Maximal exponenent under which we have no precission loss on double 1.125 + // operations. Double has 52 bits of mantissa, so 2^52+1 cannot be 1.126 + // represented without loss. 1.127 + static const uint16_t MaxTruncatableExponent = mozilla::FloatingPoint<double>::ExponentShift; 1.128 + 1.129 + // Maximum exponent for finite values. 1.130 + static const uint16_t MaxFiniteExponent = mozilla::FloatingPoint<double>::ExponentBias; 1.131 + 1.132 + // An special exponent value representing all non-NaN values. This 1.133 + // includes finite values and the infinities. 1.134 + static const uint16_t IncludesInfinity = MaxFiniteExponent + 1; 1.135 + 1.136 + // An special exponent value representing all possible double-precision 1.137 + // values. This includes finite values, the infinities, and NaNs. 1.138 + static const uint16_t IncludesInfinityAndNaN = UINT16_MAX; 1.139 + 1.140 + // This range class uses int32_t ranges, but has several interfaces which 1.141 + // use int64_t, which either holds an int32_t value, or one of the following 1.142 + // special values which mean a value which is beyond the int32 range, 1.143 + // potentially including infinity or NaN. These special values are 1.144 + // guaranteed to compare greater, and less than, respectively, any int32_t 1.145 + // value. 1.146 + static const int64_t NoInt32UpperBound = int64_t(JSVAL_INT_MAX) + 1; 1.147 + static const int64_t NoInt32LowerBound = int64_t(JSVAL_INT_MIN) - 1; 1.148 + 1.149 + private: 1.150 + // Absolute ranges. 1.151 + // 1.152 + // We represent ranges where the endpoints can be in the set: 1.153 + // {-infty} U [INT_MIN, INT_MAX] U {infty}. A bound of +/- 1.154 + // infty means that the value may have overflowed in that 1.155 + // direction. When computing the range of an integer 1.156 + // instruction, the ranges of the operands can be clamped to 1.157 + // [INT_MIN, INT_MAX], since if they had overflowed they would 1.158 + // no longer be integers. This is important for optimizations 1.159 + // and somewhat subtle. 1.160 + // 1.161 + // N.B.: All of the operations that compute new ranges based 1.162 + // on existing ranges will ignore the hasInt32*Bound_ flags of the 1.163 + // input ranges; that is, they implicitly clamp the ranges of 1.164 + // the inputs to [INT_MIN, INT_MAX]. Therefore, while our range might 1.165 + // be unbounded (and could overflow), when using this information to 1.166 + // propagate through other ranges, we disregard this fact; if that code 1.167 + // executes, then the overflow did not occur, so we may safely assume 1.168 + // that the range is [INT_MIN, INT_MAX] instead. 1.169 + // 1.170 + // To facilitate this trick, we maintain the invariants that: 1.171 + // 1) hasInt32LowerBound_ == false implies lower_ == JSVAL_INT_MIN 1.172 + // 2) hasInt32UpperBound_ == false implies upper_ == JSVAL_INT_MAX 1.173 + // 1.174 + // As a second and less precise range analysis, we represent the maximal 1.175 + // exponent taken by a value. The exponent is calculated by taking the 1.176 + // absolute value and looking at the position of the highest bit. All 1.177 + // exponent computation have to be over-estimations of the actual result. On 1.178 + // the Int32 this over approximation is rectified. 1.179 + 1.180 + int32_t lower_; 1.181 + bool hasInt32LowerBound_; 1.182 + 1.183 + int32_t upper_; 1.184 + bool hasInt32UpperBound_; 1.185 + 1.186 + bool canHaveFractionalPart_; 1.187 + uint16_t max_exponent_; 1.188 + 1.189 + // Any symbolic lower or upper bound computed for this term. 1.190 + const SymbolicBound *symbolicLower_; 1.191 + const SymbolicBound *symbolicUpper_; 1.192 + 1.193 + // This function simply makes several JS_ASSERTs to verify the internal 1.194 + // consistency of this range. 1.195 + void assertInvariants() const { 1.196 + // Basic sanity :). 1.197 + JS_ASSERT(lower_ <= upper_); 1.198 + 1.199 + // When hasInt32LowerBound_ or hasInt32UpperBound_ are false, we set 1.200 + // lower_ and upper_ to these specific values as it simplifies the 1.201 + // implementation in some places. 1.202 + JS_ASSERT_IF(!hasInt32LowerBound_, lower_ == JSVAL_INT_MIN); 1.203 + JS_ASSERT_IF(!hasInt32UpperBound_, upper_ == JSVAL_INT_MAX); 1.204 + 1.205 + // max_exponent_ must be one of three possible things. 1.206 + JS_ASSERT(max_exponent_ <= MaxFiniteExponent || 1.207 + max_exponent_ == IncludesInfinity || 1.208 + max_exponent_ == IncludesInfinityAndNaN); 1.209 + 1.210 + // Forbid the max_exponent_ field from implying better bounds for 1.211 + // lower_/upper_ fields. We have to add 1 to the max_exponent_ when 1.212 + // canHaveFractionalPart_ is true in order to accomodate fractional 1.213 + // offsets. For example, 2147483647.9 is greater than INT32_MAX, so a 1.214 + // range containing that value will have hasInt32UpperBound_ set to 1.215 + // false, however that value also has exponent 30, which is strictly 1.216 + // less than MaxInt32Exponent. For another example, 1.9 has an exponent 1.217 + // of 0 but requires upper_ to be at least 2, which has exponent 1. 1.218 + JS_ASSERT_IF(!hasInt32LowerBound_ || !hasInt32UpperBound_, 1.219 + max_exponent_ + canHaveFractionalPart_ >= MaxInt32Exponent); 1.220 + JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >= 1.221 + mozilla::FloorLog2(mozilla::Abs(upper_))); 1.222 + JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >= 1.223 + mozilla::FloorLog2(mozilla::Abs(lower_))); 1.224 + 1.225 + // The following are essentially static assertions, but FloorLog2 isn't 1.226 + // trivially suitable for constexpr :(. 1.227 + JS_ASSERT(mozilla::FloorLog2(JSVAL_INT_MIN) == MaxInt32Exponent); 1.228 + JS_ASSERT(mozilla::FloorLog2(JSVAL_INT_MAX) == 30); 1.229 + JS_ASSERT(mozilla::FloorLog2(UINT32_MAX) == MaxUInt32Exponent); 1.230 + JS_ASSERT(mozilla::FloorLog2(0) == 0); 1.231 + } 1.232 + 1.233 + // Set the lower_ and hasInt32LowerBound_ values. 1.234 + void setLowerInit(int64_t x) { 1.235 + if (x > JSVAL_INT_MAX) { 1.236 + lower_ = JSVAL_INT_MAX; 1.237 + hasInt32LowerBound_ = true; 1.238 + } else if (x < JSVAL_INT_MIN) { 1.239 + lower_ = JSVAL_INT_MIN; 1.240 + hasInt32LowerBound_ = false; 1.241 + } else { 1.242 + lower_ = int32_t(x); 1.243 + hasInt32LowerBound_ = true; 1.244 + } 1.245 + } 1.246 + // Set the upper_ and hasInt32UpperBound_ values. 1.247 + void setUpperInit(int64_t x) { 1.248 + if (x > JSVAL_INT_MAX) { 1.249 + upper_ = JSVAL_INT_MAX; 1.250 + hasInt32UpperBound_ = false; 1.251 + } else if (x < JSVAL_INT_MIN) { 1.252 + upper_ = JSVAL_INT_MIN; 1.253 + hasInt32UpperBound_ = true; 1.254 + } else { 1.255 + upper_ = int32_t(x); 1.256 + hasInt32UpperBound_ = true; 1.257 + } 1.258 + } 1.259 + 1.260 + // Compute the least exponent value that would be compatible with the 1.261 + // values of lower() and upper(). 1.262 + // 1.263 + // Note: 1.264 + // exponent of JSVAL_INT_MIN == 31 1.265 + // exponent of JSVAL_INT_MAX == 30 1.266 + uint16_t exponentImpliedByInt32Bounds() const { 1.267 + // The number of bits needed to encode |max| is the power of 2 plus one. 1.268 + uint32_t max = Max(mozilla::Abs(lower()), mozilla::Abs(upper())); 1.269 + uint16_t result = mozilla::FloorLog2(max); 1.270 + JS_ASSERT(result == (max == 0 ? 0 : mozilla::ExponentComponent(double(max)))); 1.271 + return result; 1.272 + } 1.273 + 1.274 + // When converting a range which contains fractional values to a range 1.275 + // containing only integers, the old max_exponent_ value may imply a better 1.276 + // lower and/or upper bound than was previously available, because they no 1.277 + // longer need to be conservative about fractional offsets and the ends of 1.278 + // the range. 1.279 + // 1.280 + // Given an exponent value and pointers to the lower and upper bound values, 1.281 + // this function refines the lower and upper bound values to the tighest 1.282 + // bound for integer values implied by the exponent. 1.283 + static void refineInt32BoundsByExponent(uint16_t e, int32_t *l, int32_t *h) { 1.284 + if (e < MaxInt32Exponent) { 1.285 + // pow(2, max_exponent_+1)-1 to compute a maximum absolute value. 1.286 + int32_t limit = (uint32_t(1) << (e + 1)) - 1; 1.287 + *h = Min(*h, limit); 1.288 + *l = Max(*l, -limit); 1.289 + } 1.290 + } 1.291 + 1.292 + // If the value of any of the fields implies a stronger possible value for 1.293 + // any other field, update that field to the stronger value. The range must 1.294 + // be completely valid before and it is guaranteed to be kept valid. 1.295 + void optimize() { 1.296 + assertInvariants(); 1.297 + 1.298 + if (hasInt32Bounds()) { 1.299 + // Examine lower() and upper(), and if they imply a better exponent 1.300 + // bound than max_exponent_, set that value as the new 1.301 + // max_exponent_. 1.302 + uint16_t newExponent = exponentImpliedByInt32Bounds(); 1.303 + if (newExponent < max_exponent_) { 1.304 + max_exponent_ = newExponent; 1.305 + assertInvariants(); 1.306 + } 1.307 + 1.308 + // If we have a completely precise range, the value is an integer, 1.309 + // since we can only represent integers. 1.310 + if (canHaveFractionalPart_ && lower_ == upper_) { 1.311 + canHaveFractionalPart_ = false; 1.312 + assertInvariants(); 1.313 + } 1.314 + } 1.315 + } 1.316 + 1.317 + // Set the range fields to the given raw values. 1.318 + void rawInitialize(int32_t l, bool lb, int32_t h, bool hb, bool f, uint16_t e) { 1.319 + lower_ = l; 1.320 + hasInt32LowerBound_ = lb; 1.321 + upper_ = h; 1.322 + hasInt32UpperBound_ = hb; 1.323 + canHaveFractionalPart_ = f; 1.324 + max_exponent_ = e; 1.325 + optimize(); 1.326 + } 1.327 + 1.328 + // Construct a range from the given raw values. 1.329 + Range(int32_t l, bool lb, int32_t h, bool hb, bool f, uint16_t e) 1.330 + : symbolicLower_(nullptr), 1.331 + symbolicUpper_(nullptr) 1.332 + { 1.333 + rawInitialize(l, lb, h, hb, f, e); 1.334 + } 1.335 + 1.336 + public: 1.337 + Range() 1.338 + : symbolicLower_(nullptr), 1.339 + symbolicUpper_(nullptr) 1.340 + { 1.341 + setUnknown(); 1.342 + } 1.343 + 1.344 + Range(int64_t l, int64_t h, bool f = false, uint16_t e = MaxInt32Exponent) 1.345 + : symbolicLower_(nullptr), 1.346 + symbolicUpper_(nullptr) 1.347 + { 1.348 + set(l, h, f, e); 1.349 + } 1.350 + 1.351 + Range(const Range &other) 1.352 + : lower_(other.lower_), 1.353 + hasInt32LowerBound_(other.hasInt32LowerBound_), 1.354 + upper_(other.upper_), 1.355 + hasInt32UpperBound_(other.hasInt32UpperBound_), 1.356 + canHaveFractionalPart_(other.canHaveFractionalPart_), 1.357 + max_exponent_(other.max_exponent_), 1.358 + symbolicLower_(nullptr), 1.359 + symbolicUpper_(nullptr) 1.360 + { 1.361 + assertInvariants(); 1.362 + } 1.363 + 1.364 + // Construct a range from the given MDefinition. This differs from the 1.365 + // MDefinition's range() method in that it describes the range of values 1.366 + // *after* any bailout checks. 1.367 + Range(const MDefinition *def); 1.368 + 1.369 + static Range *NewInt32Range(TempAllocator &alloc, int32_t l, int32_t h) { 1.370 + return new(alloc) Range(l, h, false, MaxInt32Exponent); 1.371 + } 1.372 + 1.373 + static Range *NewUInt32Range(TempAllocator &alloc, uint32_t l, uint32_t h) { 1.374 + // For now, just pass them to the constructor as int64_t values. 1.375 + // They'll become unbounded if they're not in the int32_t range. 1.376 + return new(alloc) Range(l, h, false, MaxUInt32Exponent); 1.377 + } 1.378 + 1.379 + static Range *NewDoubleRange(TempAllocator &alloc, double l, double h) { 1.380 + if (mozilla::IsNaN(l) && mozilla::IsNaN(h)) 1.381 + return nullptr; 1.382 + 1.383 + Range *r = new(alloc) Range(); 1.384 + r->setDouble(l, h); 1.385 + return r; 1.386 + } 1.387 + 1.388 + void print(Sprinter &sp) const; 1.389 + void dump(FILE *fp) const; 1.390 + void dump() const; 1.391 + bool update(const Range *other); 1.392 + 1.393 + // Unlike the other operations, unionWith is an in-place 1.394 + // modification. This is to avoid a bunch of useless extra 1.395 + // copying when chaining together unions when handling Phi 1.396 + // nodes. 1.397 + void unionWith(const Range *other); 1.398 + static Range *intersect(TempAllocator &alloc, const Range *lhs, const Range *rhs, 1.399 + bool *emptyRange); 1.400 + static Range *add(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.401 + static Range *sub(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.402 + static Range *mul(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.403 + static Range *and_(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.404 + static Range *or_(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.405 + static Range *xor_(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.406 + static Range *not_(TempAllocator &alloc, const Range *op); 1.407 + static Range *lsh(TempAllocator &alloc, const Range *lhs, int32_t c); 1.408 + static Range *rsh(TempAllocator &alloc, const Range *lhs, int32_t c); 1.409 + static Range *ursh(TempAllocator &alloc, const Range *lhs, int32_t c); 1.410 + static Range *lsh(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.411 + static Range *rsh(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.412 + static Range *ursh(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.413 + static Range *abs(TempAllocator &alloc, const Range *op); 1.414 + static Range *min(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.415 + static Range *max(TempAllocator &alloc, const Range *lhs, const Range *rhs); 1.416 + 1.417 + static bool negativeZeroMul(const Range *lhs, const Range *rhs); 1.418 + 1.419 + bool isUnknownInt32() const { 1.420 + return isInt32() && lower() == INT32_MIN && upper() == INT32_MAX; 1.421 + } 1.422 + 1.423 + bool isUnknown() const { 1.424 + return !hasInt32LowerBound_ && 1.425 + !hasInt32UpperBound_ && 1.426 + canHaveFractionalPart_ && 1.427 + max_exponent_ == IncludesInfinityAndNaN; 1.428 + } 1.429 + 1.430 + bool hasInt32LowerBound() const { 1.431 + return hasInt32LowerBound_; 1.432 + } 1.433 + bool hasInt32UpperBound() const { 1.434 + return hasInt32UpperBound_; 1.435 + } 1.436 + 1.437 + // Test whether the value is known to be within [INT32_MIN,INT32_MAX]. 1.438 + // Note that this does not necessarily mean the value is an integer. 1.439 + bool hasInt32Bounds() const { 1.440 + return hasInt32LowerBound() && hasInt32UpperBound(); 1.441 + } 1.442 + 1.443 + // Test whether the value is known to be representable as an int32. 1.444 + bool isInt32() const { 1.445 + return hasInt32Bounds() && !canHaveFractionalPart(); 1.446 + } 1.447 + 1.448 + // Test whether the given value is known to be either 0 or 1. 1.449 + bool isBoolean() const { 1.450 + return lower() >= 0 && upper() <= 1 && !canHaveFractionalPart(); 1.451 + } 1.452 + 1.453 + bool canHaveRoundingErrors() const { 1.454 + return canHaveFractionalPart() || max_exponent_ >= MaxTruncatableExponent; 1.455 + } 1.456 + 1.457 + // Test whether the range contains zero. 1.458 + bool canBeZero() const { 1.459 + return lower_ <= 0 && upper_ >= 0; 1.460 + } 1.461 + 1.462 + // Test whether the range contains NaN values. 1.463 + bool canBeNaN() const { 1.464 + return max_exponent_ == IncludesInfinityAndNaN; 1.465 + } 1.466 + 1.467 + // Test whether the range contains infinities or NaN values. 1.468 + bool canBeInfiniteOrNaN() const { 1.469 + return max_exponent_ >= IncludesInfinity; 1.470 + } 1.471 + 1.472 + bool canHaveFractionalPart() const { 1.473 + return canHaveFractionalPart_; 1.474 + } 1.475 + 1.476 + uint16_t exponent() const { 1.477 + JS_ASSERT(!canBeInfiniteOrNaN()); 1.478 + return max_exponent_; 1.479 + } 1.480 + 1.481 + uint16_t numBits() const { 1.482 + return exponent() + 1; // 2^0 -> 1 1.483 + } 1.484 + 1.485 + // Return the lower bound. Asserts that the value has an int32 bound. 1.486 + int32_t lower() const { 1.487 + JS_ASSERT(hasInt32LowerBound()); 1.488 + return lower_; 1.489 + } 1.490 + 1.491 + // Return the upper bound. Asserts that the value has an int32 bound. 1.492 + int32_t upper() const { 1.493 + JS_ASSERT(hasInt32UpperBound()); 1.494 + return upper_; 1.495 + } 1.496 + 1.497 + // Test whether all values in this range can are finite and negative. 1.498 + bool isFiniteNegative() const { 1.499 + return upper_ < 0 && !canBeInfiniteOrNaN(); 1.500 + } 1.501 + 1.502 + // Test whether all values in this range can are finite and non-negative. 1.503 + bool isFiniteNonNegative() const { 1.504 + return lower_ >= 0 && !canBeInfiniteOrNaN(); 1.505 + } 1.506 + 1.507 + // Test whether a value in this range can possibly be a finite 1.508 + // negative value. 1.509 + bool canBeFiniteNegative() const { 1.510 + return lower_ < 0; 1.511 + } 1.512 + 1.513 + // Test whether a value in this range can possibly be a finite 1.514 + // non-negative value. 1.515 + bool canBeFiniteNonNegative() const { 1.516 + return upper_ >= 0; 1.517 + } 1.518 + 1.519 + // Set this range to have a lower bound not less than x. 1.520 + void refineLower(int32_t x) { 1.521 + assertInvariants(); 1.522 + hasInt32LowerBound_ = true; 1.523 + lower_ = Max(lower_, x); 1.524 + optimize(); 1.525 + } 1.526 + 1.527 + // Set this range to have an upper bound not greater than x. 1.528 + void refineUpper(int32_t x) { 1.529 + assertInvariants(); 1.530 + hasInt32UpperBound_ = true; 1.531 + upper_ = Min(upper_, x); 1.532 + optimize(); 1.533 + } 1.534 + 1.535 + void setInt32(int32_t l, int32_t h) { 1.536 + hasInt32LowerBound_ = true; 1.537 + hasInt32UpperBound_ = true; 1.538 + lower_ = l; 1.539 + upper_ = h; 1.540 + canHaveFractionalPart_ = false; 1.541 + max_exponent_ = exponentImpliedByInt32Bounds(); 1.542 + assertInvariants(); 1.543 + } 1.544 + 1.545 + void setDouble(double l, double h); 1.546 + 1.547 + void setUnknown() { 1.548 + set(NoInt32LowerBound, NoInt32UpperBound, true, IncludesInfinityAndNaN); 1.549 + JS_ASSERT(isUnknown()); 1.550 + } 1.551 + 1.552 + void set(int64_t l, int64_t h, bool f, uint16_t e) { 1.553 + max_exponent_ = e; 1.554 + canHaveFractionalPart_ = f; 1.555 + setLowerInit(l); 1.556 + setUpperInit(h); 1.557 + optimize(); 1.558 + } 1.559 + 1.560 + // Make the lower end of this range at least INT32_MIN, and make 1.561 + // the upper end of this range at most INT32_MAX. 1.562 + void clampToInt32(); 1.563 + 1.564 + // If this range exceeds int32_t range, at either or both ends, change 1.565 + // it to int32_t range. Otherwise do nothing. 1.566 + void wrapAroundToInt32(); 1.567 + 1.568 + // If this range exceeds [0, 32) range, at either or both ends, change 1.569 + // it to the [0, 32) range. Otherwise do nothing. 1.570 + void wrapAroundToShiftCount(); 1.571 + 1.572 + // If this range exceeds [0, 1] range, at either or both ends, change 1.573 + // it to the [0, 1] range. Otherwise do nothing. 1.574 + void wrapAroundToBoolean(); 1.575 + 1.576 + const SymbolicBound *symbolicLower() const { 1.577 + return symbolicLower_; 1.578 + } 1.579 + const SymbolicBound *symbolicUpper() const { 1.580 + return symbolicUpper_; 1.581 + } 1.582 + 1.583 + void setSymbolicLower(SymbolicBound *bound) { 1.584 + symbolicLower_ = bound; 1.585 + } 1.586 + void setSymbolicUpper(SymbolicBound *bound) { 1.587 + symbolicUpper_ = bound; 1.588 + } 1.589 +}; 1.590 + 1.591 +} // namespace jit 1.592 +} // namespace js 1.593 + 1.594 +#endif /* jit_RangeAnalysis_h */