| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "Backend.h"
- bool ValueInfo::HasIntConstantValue(const bool includeLikelyInt) const
- {
- int32 constantValue;
- return TryGetIntConstantValue(&constantValue, includeLikelyInt);
- }
- bool ValueInfo::TryGetInt64ConstantValue(int64 *const intValueRef, const bool isUnsigned) const
- {
- Assert(intValueRef);
- if (TryGetIntConstantValue(intValueRef, isUnsigned))
- {
- return true;
- }
- else
- {
- int32 int32ValueRef;
- if (TryGetIntConstantValue(&int32ValueRef, false))
- {
- if (isUnsigned)
- {
- *intValueRef = (uint)int32ValueRef;
- }
- else
- {
- *intValueRef = int32ValueRef;
- }
- return true;
- }
- }
- return false;
- }
- bool ValueInfo::TryGetIntConstantValue(int64 *const intValueRef, const bool isUnsigned) const
- {
- Assert(intValueRef);
- if (structureKind == ValueStructureKind::Int64Constant)
- {
- *intValueRef = AsInt64Constant()->IntValue();
- return true;
- }
- return false;
- }
- bool ValueInfo::TryGetIntConstantValue(int32 *const intValueRef, const bool includeLikelyInt) const
- {
- Assert(intValueRef);
- if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
- {
- return false;
- }
- switch (structureKind)
- {
- case ValueStructureKind::IntConstant:
- if (!includeLikelyInt || IsInt())
- {
- *intValueRef = AsIntConstant()->IntValue();
- return true;
- }
- break;
- case ValueStructureKind::IntRange:
- Assert(includeLikelyInt && !IsInt() || !AsIntRange()->IsConstant());
- break;
- case ValueStructureKind::IntBounded:
- {
- const IntConstantBounds bounds(AsIntBounded()->Bounds()->ConstantBounds());
- if (bounds.IsConstant())
- {
- *intValueRef = bounds.LowerBound();
- return true;
- }
- break;
- }
- }
- return false;
- }
- bool ValueInfo::TryGetIntConstantLowerBound(int32 *const intConstantBoundRef, const bool includeLikelyInt) const
- {
- Assert(intConstantBoundRef);
- if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
- {
- return false;
- }
- switch (structureKind)
- {
- case ValueStructureKind::IntConstant:
- if (!includeLikelyInt || IsInt())
- {
- *intConstantBoundRef = AsIntConstant()->IntValue();
- return true;
- }
- break;
- case ValueStructureKind::IntRange:
- if (!includeLikelyInt || IsInt())
- {
- *intConstantBoundRef = AsIntRange()->LowerBound();
- return true;
- }
- break;
- case ValueStructureKind::IntBounded:
- *intConstantBoundRef = AsIntBounded()->Bounds()->ConstantLowerBound();
- return true;
- }
- *intConstantBoundRef = IsTaggedInt() ? Js::Constants::Int31MinValue : IntConstMin;
- return true;
- }
- bool ValueInfo::TryGetIntConstantUpperBound(int32 *const intConstantBoundRef, const bool includeLikelyInt) const
- {
- Assert(intConstantBoundRef);
- if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
- {
- return false;
- }
- switch (structureKind)
- {
- case ValueStructureKind::IntConstant:
- if (!includeLikelyInt || IsInt())
- {
- *intConstantBoundRef = AsIntConstant()->IntValue();
- return true;
- }
- break;
- case ValueStructureKind::IntRange:
- if (!includeLikelyInt || IsInt())
- {
- *intConstantBoundRef = AsIntRange()->UpperBound();
- return true;
- }
- break;
- case ValueStructureKind::IntBounded:
- *intConstantBoundRef = AsIntBounded()->Bounds()->ConstantUpperBound();
- return true;
- }
- *intConstantBoundRef = IsTaggedInt() ? Js::Constants::Int31MaxValue : IntConstMax;
- return true;
- }
- bool ValueInfo::TryGetIntConstantBounds(IntConstantBounds *const intConstantBoundsRef, const bool includeLikelyInt) const
- {
- Assert(intConstantBoundsRef);
- if (!(includeLikelyInt ? IsLikelyInt() : IsInt()))
- {
- return false;
- }
- switch (structureKind)
- {
- case ValueStructureKind::IntConstant:
- if (!includeLikelyInt || IsInt())
- {
- const int32 intValue = AsIntConstant()->IntValue();
- *intConstantBoundsRef = IntConstantBounds(intValue, intValue);
- return true;
- }
- break;
- case ValueStructureKind::IntRange:
- if (!includeLikelyInt || IsInt())
- {
- *intConstantBoundsRef = *AsIntRange();
- return true;
- }
- break;
- case ValueStructureKind::IntBounded:
- *intConstantBoundsRef = AsIntBounded()->Bounds()->ConstantBounds();
- return true;
- }
- *intConstantBoundsRef =
- IsTaggedInt()
- ? IntConstantBounds(Js::Constants::Int31MinValue, Js::Constants::Int31MaxValue)
- : IntConstantBounds(INT32_MIN, INT32_MAX);
- return true;
- }
- bool ValueInfo::WasNegativeZeroPreventedByBailout() const
- {
- if (!IsInt())
- {
- return false;
- }
- switch (structureKind)
- {
- case ValueStructureKind::IntRange:
- return AsIntRange()->WasNegativeZeroPreventedByBailout();
- case ValueStructureKind::IntBounded:
- return AsIntBounded()->WasNegativeZeroPreventedByBailout();
- }
- return false;
- }
- bool ValueInfo::IsEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- const bool result =
- IsEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2) ||
- IsEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1);
- Assert(!result || !IsNotEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2));
- Assert(!result || !IsNotEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1));
- return result;
- }
- bool ValueInfo::IsNotEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- const bool result =
- IsNotEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2) ||
- IsNotEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1);
- Assert(!result || !IsEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2));
- Assert(!result || !IsEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1));
- return result;
- }
- bool ValueInfo::IsEqualTo_NoConverse(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return
- IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2) &&
- IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2);
- }
- bool ValueInfo::IsNotEqualTo_NoConverse(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return
- IsGreaterThan(src1Value, min1, max1, src2Value, min2, max2) ||
- IsLessThan(src1Value, min1, max1, src2Value, min2, max2);
- }
- bool ValueInfo::IsGreaterThanOrEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 0);
- }
- bool ValueInfo::IsGreaterThan(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return IsGreaterThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 1);
- }
- bool ValueInfo::IsLessThanOrEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, 0);
- }
- bool ValueInfo::IsLessThan(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2)
- {
- return IsLessThanOrEqualTo(src1Value, min1, max1, src2Value, min2, max2, -1);
- }
- bool ValueInfo::IsGreaterThanOrEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2,
- const int src2Offset)
- {
- return
- IsGreaterThanOrEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2, src2Offset) ||
- src2Offset == IntConstMin ||
- IsLessThanOrEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1, -src2Offset);
- }
- bool ValueInfo::IsLessThanOrEqualTo(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2,
- const int src2Offset)
- {
- return
- IsLessThanOrEqualTo_NoConverse(src1Value, min1, max1, src2Value, min2, max2, src2Offset) ||
- (
- src2Offset != IntConstMin &&
- IsGreaterThanOrEqualTo_NoConverse(src2Value, min2, max2, src1Value, min1, max1, -src2Offset)
- );
- }
- bool ValueInfo::IsGreaterThanOrEqualTo_NoConverse(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2,
- const int src2Offset)
- {
- Assert(src1Value || min1 == max1);
- Assert(!src1Value || src1Value->GetValueInfo()->IsLikelyInt());
- Assert(src2Value || min2 == max2);
- Assert(!src2Value || src2Value->GetValueInfo()->IsLikelyInt());
- if (src1Value)
- {
- if (src2Value && src1Value->GetValueNumber() == src2Value->GetValueNumber())
- {
- return src2Offset <= 0;
- }
- ValueInfo const * const src1ValueInfo = src1Value->GetValueInfo();
- if (src1ValueInfo->structureKind == ValueStructureKind::IntBounded)
- {
- const IntBounds *const bounds = src1ValueInfo->AsIntBounded()->Bounds();
- return
- src2Value
- ? bounds->IsGreaterThanOrEqualTo(src2Value, src2Offset)
- : bounds->IsGreaterThanOrEqualTo(min2, src2Offset);
- }
- }
- return IntBounds::IsGreaterThanOrEqualTo(min1, max2, src2Offset);
- }
- bool ValueInfo::IsLessThanOrEqualTo_NoConverse(
- const Value *const src1Value,
- const int32 min1,
- const int32 max1,
- const Value *const src2Value,
- const int32 min2,
- const int32 max2,
- const int src2Offset)
- {
- Assert(src1Value || min1 == max1);
- Assert(!src1Value || src1Value->GetValueInfo()->IsLikelyInt());
- Assert(src2Value || min2 == max2);
- Assert(!src2Value || src2Value->GetValueInfo()->IsLikelyInt());
- if (src1Value)
- {
- if (src2Value && src1Value->GetValueNumber() == src2Value->GetValueNumber())
- {
- return src2Offset >= 0;
- }
- ValueInfo const * const src1ValueInfo = src1Value->GetValueInfo();
- if (src1ValueInfo->structureKind == ValueStructureKind::IntBounded)
- {
- const IntBounds *const bounds = src1ValueInfo->AsIntBounded()->Bounds();
- return
- src2Value
- ? bounds->IsLessThanOrEqualTo(src2Value, src2Offset)
- : bounds->IsLessThanOrEqualTo(min2, src2Offset);
- }
- }
- return IntBounds::IsLessThanOrEqualTo(max1, min2, src2Offset);
- }
- bool
- ValueInfo::IsGeneric() const
- {
- return structureKind == ValueStructureKind::Generic;
- }
- bool
- ValueInfo::IsIntConstant() const
- {
- return IsInt() && structureKind == ValueStructureKind::IntConstant;
- }
- bool
- ValueInfo::IsInt64Constant() const
- {
- return IsInt() && structureKind == ValueStructureKind::Int64Constant;
- }
- const IntConstantValueInfo *
- ValueInfo::AsIntConstant() const
- {
- Assert(IsIntConstant());
- return static_cast<const IntConstantValueInfo *>(this);
- }
- const Int64ConstantValueInfo *
- ValueInfo::AsInt64Constant() const
- {
- Assert(IsInt64Constant());
- return static_cast<const Int64ConstantValueInfo *>(this);
- }
- bool
- ValueInfo::IsIntRange() const
- {
- return IsInt() && structureKind == ValueStructureKind::IntRange;
- }
- const IntRangeValueInfo *
- ValueInfo::AsIntRange() const
- {
- Assert(IsIntRange());
- return static_cast<const IntRangeValueInfo *>(this);
- }
- bool
- ValueInfo::IsIntBounded() const
- {
- const bool isIntBounded = IsLikelyInt() && structureKind == ValueStructureKind::IntBounded;
- // Bounds for definitely int values should have relative bounds, otherwise those values should use one of the other value
- // infos
- Assert(!isIntBounded || static_cast<const IntBoundedValueInfo *>(this)->Bounds()->RequiresIntBoundedValueInfo(Type()));
- return isIntBounded;
- }
- const IntBoundedValueInfo *
- ValueInfo::AsIntBounded() const
- {
- Assert(IsIntBounded());
- return static_cast<const IntBoundedValueInfo *>(this);
- }
- bool
- ValueInfo::IsFloatConstant() const
- {
- return IsFloat() && structureKind == ValueStructureKind::FloatConstant;
- }
- FloatConstantValueInfo *
- ValueInfo::AsFloatConstant()
- {
- Assert(IsFloatConstant());
- return static_cast<FloatConstantValueInfo *>(this);
- }
- const FloatConstantValueInfo *
- ValueInfo::AsFloatConstant() const
- {
- Assert(IsFloatConstant());
- return static_cast<const FloatConstantValueInfo *>(this);
- }
- bool
- ValueInfo::IsVarConstant() const
- {
- return structureKind == ValueStructureKind::VarConstant;
- }
- VarConstantValueInfo *
- ValueInfo::AsVarConstant()
- {
- Assert(IsVarConstant());
- return static_cast<VarConstantValueInfo *>(this);
- }
- bool
- ValueInfo::IsJsType() const
- {
- Assert(!(structureKind == ValueStructureKind::JsType && !IsUninitialized()));
- return structureKind == ValueStructureKind::JsType;
- }
- JsTypeValueInfo *
- ValueInfo::AsJsType()
- {
- Assert(IsJsType());
- return static_cast<JsTypeValueInfo *>(this);
- }
- const JsTypeValueInfo *
- ValueInfo::AsJsType() const
- {
- Assert(IsJsType());
- return static_cast<const JsTypeValueInfo *>(this);
- }
- bool
- ValueInfo::IsArrayValueInfo() const
- {
- return IsAnyOptimizedArray() && structureKind == ValueStructureKind::Array;
- }
- const ArrayValueInfo *
- ValueInfo::AsArrayValueInfo() const
- {
- Assert(IsArrayValueInfo());
- return static_cast<const ArrayValueInfo *>(this);
- }
- ArrayValueInfo *
- ValueInfo::AsArrayValueInfo()
- {
- Assert(IsArrayValueInfo());
- return static_cast<ArrayValueInfo *>(this);
- }
- ValueInfo *
- ValueInfo::SpecializeToInt32(JitArenaAllocator *const allocator, const bool isForLoopBackEdgeCompensation)
- {
- // Int specialization in some uncommon loop cases involving dependencies, needs to allow specializing values of arbitrary
- // types, even values that are definitely not int, to compensate for aggressive assumptions made by a loop prepass. In all
- // other cases, only values that are likely int may be int-specialized.
- Assert(IsUninitialized() || IsLikelyInt() || isForLoopBackEdgeCompensation);
- if (IsInt())
- {
- return this;
- }
- if (!IsIntBounded())
- {
- ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
- newValueInfo->Type() = ValueType::GetInt(true);
- return newValueInfo;
- }
- const IntBoundedValueInfo *const boundedValueInfo = AsIntBounded();
- const IntBounds *const bounds = boundedValueInfo->Bounds();
- const IntConstantBounds constantBounds = bounds->ConstantBounds();
- if (bounds->RequiresIntBoundedValueInfo())
- {
- IntBoundedValueInfo *const newValueInfo = boundedValueInfo->Copy(allocator);
- newValueInfo->Type() = constantBounds.GetValueType();
- return newValueInfo;
- }
- ValueInfo *const newValueInfo =
- constantBounds.IsConstant()
- ? static_cast<ValueInfo *>(IntConstantValueInfo::New(allocator, constantBounds.LowerBound()))
- : IntRangeValueInfo::New(allocator, constantBounds.LowerBound(), constantBounds.UpperBound(), false);
- newValueInfo->SetSymStore(GetSymStore());
- return newValueInfo;
- }
- ValueInfo *
- ValueInfo::SpecializeToFloat64(JitArenaAllocator *const allocator)
- {
- if (IsNumber())
- {
- return this;
- }
- ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
- // If the value type was likely int, after float-specializing, it's preferable to use Int_Number rather than Float, as the
- // former is also likely int and allows int specialization later.
- newValueInfo->Type() = IsLikelyInt() ? Type().ToDefiniteAnyNumber() : Type().ToDefiniteAnyFloat();
- return newValueInfo;
- }
- // SIMD_JS
- ValueInfo *
- ValueInfo::SpecializeToSimd128(IRType type, JitArenaAllocator *const allocator)
- {
- switch (type)
- {
- case TySimd128F4:
- return SpecializeToSimd128F4(allocator);
- case TySimd128I4:
- return SpecializeToSimd128I4(allocator);
- default:
- Assert(UNREACHED);
- return nullptr;
- }
- }
- ValueInfo *
- ValueInfo::SpecializeToSimd128F4(JitArenaAllocator *const allocator)
- {
- if (IsSimd128Float32x4())
- {
- return this;
- }
- ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
- newValueInfo->Type() = ValueType::GetSimd128(ObjectType::Simd128Float32x4);
- return newValueInfo;
- }
- ValueInfo *
- ValueInfo::SpecializeToSimd128I4(JitArenaAllocator *const allocator)
- {
- if (IsSimd128Int32x4())
- {
- return this;
- }
- ValueInfo *const newValueInfo = CopyWithGenericStructureKind(allocator);
- newValueInfo->Type() = ValueType::GetSimd128(ObjectType::Simd128Int32x4);
- return newValueInfo;
- }
- bool
- ValueInfo::GetIsShared() const
- {
- return IsJsType() ? AsJsType()->GetIsShared() : false;
- }
- void
- ValueInfo::SetIsShared()
- {
- if (IsJsType()) AsJsType()->SetIsShared();
- }
- ValueInfo *
- ValueInfo::Copy(JitArenaAllocator * allocator)
- {
- if (IsIntConstant())
- {
- return AsIntConstant()->Copy(allocator);
- }
- if (IsIntRange())
- {
- return AsIntRange()->Copy(allocator);
- }
- if (IsIntBounded())
- {
- return AsIntBounded()->Copy(allocator);
- }
- if (IsFloatConstant())
- {
- return AsFloatConstant()->Copy(allocator);
- }
- if (IsJsType())
- {
- return AsJsType()->Copy(allocator);
- }
- if (IsArrayValueInfo())
- {
- return AsArrayValueInfo()->Copy(allocator);
- }
- return CopyWithGenericStructureKind(allocator);
- }
- bool
- ValueInfo::GetIntValMinMax(int *pMin, int *pMax, bool doAggressiveIntTypeSpec)
- {
- IntConstantBounds intConstantBounds;
- if (TryGetIntConstantBounds(&intConstantBounds, doAggressiveIntTypeSpec))
- {
- *pMin = intConstantBounds.LowerBound();
- *pMax = intConstantBounds.UpperBound();
- return true;
- }
- Assert(!IsInt());
- Assert(!doAggressiveIntTypeSpec || !IsLikelyInt());
- return false;
- }
- ValueInfo *
- ValueInfo::MergeLikelyIntValueInfo(JitArenaAllocator* alloc, Value *toDataVal, Value *fromDataVal, ValueType const newValueType)
- {
- Assert(newValueType.IsLikelyInt());
- ValueInfo *const toDataValueInfo = toDataVal->GetValueInfo();
- ValueInfo *const fromDataValueInfo = fromDataVal->GetValueInfo();
- Assert(toDataValueInfo != fromDataValueInfo);
- bool wasNegativeZeroPreventedByBailout;
- if(newValueType.IsInt())
- {
- int32 toDataIntConstantValue, fromDataIntConstantValue;
- if (toDataValueInfo->TryGetIntConstantValue(&toDataIntConstantValue) &&
- fromDataValueInfo->TryGetIntConstantValue(&fromDataIntConstantValue) &&
- toDataIntConstantValue == fromDataIntConstantValue)
- {
- // A new value number must be created to register the fact that the value has changed. Otherwise, if the value
- // changed inside a loop, the sym may look invariant on the loop back-edge (and hence not turned into a number
- // value), and its constant value from the first iteration may be incorrectly propagated after the loop.
- return IntConstantValueInfo::New(alloc, toDataIntConstantValue);
- }
- wasNegativeZeroPreventedByBailout =
- toDataValueInfo->WasNegativeZeroPreventedByBailout() ||
- fromDataValueInfo->WasNegativeZeroPreventedByBailout();
- }
- else
- {
- wasNegativeZeroPreventedByBailout = false;
- }
- const IntBounds *const toDataValBounds =
- toDataValueInfo->IsIntBounded() ? toDataValueInfo->AsIntBounded()->Bounds() : nullptr;
- const IntBounds *const fromDataValBounds =
- fromDataValueInfo->IsIntBounded() ? fromDataValueInfo->AsIntBounded()->Bounds() : nullptr;
- if(toDataValBounds || fromDataValBounds)
- {
- const IntBounds *mergedBounds;
- if(toDataValBounds && fromDataValBounds)
- {
- mergedBounds = IntBounds::Merge(toDataVal, toDataValBounds, fromDataVal, fromDataValBounds);
- }
- else
- {
- IntConstantBounds constantBounds;
- if(toDataValBounds)
- {
- mergedBounds =
- fromDataValueInfo->TryGetIntConstantBounds(&constantBounds, true)
- ? IntBounds::Merge(toDataVal, toDataValBounds, fromDataVal, constantBounds)
- : nullptr;
- }
- else
- {
- Assert(fromDataValBounds);
- mergedBounds =
- toDataValueInfo->TryGetIntConstantBounds(&constantBounds, true)
- ? IntBounds::Merge(fromDataVal, fromDataValBounds, toDataVal, constantBounds)
- : nullptr;
- }
- }
- if(mergedBounds)
- {
- if(mergedBounds->RequiresIntBoundedValueInfo(newValueType))
- {
- return IntBoundedValueInfo::New(newValueType, mergedBounds, wasNegativeZeroPreventedByBailout, alloc);
- }
- mergedBounds->Delete();
- }
- }
- if(newValueType.IsInt())
- {
- int32 min1, max1, min2, max2;
- toDataValueInfo->GetIntValMinMax(&min1, &max1, false);
- fromDataValueInfo->GetIntValMinMax(&min2, &max2, false);
- return ValueInfo::NewIntRangeValueInfo(alloc, min(min1, min2), max(max1, max2), wasNegativeZeroPreventedByBailout);
- }
- return ValueInfo::New(alloc, newValueType);
- }
- ValueInfo * ValueInfo::NewIntRangeValueInfo(JitArenaAllocator * alloc, int32 min, int32 max, bool wasNegativeZeroPreventedByBailout)
- {
- if (min == max)
- {
- // Since int constant values are const-propped, negative zero tracking does not track them, and so it's okay to ignore
- // 'wasNegativeZeroPreventedByBailout'
- return IntConstantValueInfo::New(alloc, max);
- }
- return IntRangeValueInfo::New(alloc, min, max, wasNegativeZeroPreventedByBailout);
- }
- #if DBG_DUMP
- void ValueInfo::Dump()
- {
- if (!IsJsType()) // The value type is uninitialized for a type value
- {
- char typeStr[VALUE_TYPE_MAX_STRING_SIZE];
- Type().ToString(typeStr);
- Output::Print(_u("%S"), typeStr);
- }
- IntConstantBounds intConstantBounds;
- if (TryGetIntConstantBounds(&intConstantBounds))
- {
- if (intConstantBounds.IsConstant())
- {
- Output::Print(_u(" constant:%d"), intConstantBounds.LowerBound());
- return;
- }
- Output::Print(_u(" range:%d - %d"), intConstantBounds.LowerBound(), intConstantBounds.UpperBound());
- }
- else if (IsFloatConstant())
- {
- Output::Print(_u(" constant:%g"), AsFloatConstant()->FloatValue());
- }
- else if (IsJsType())
- {
- const JITTypeHolder type(AsJsType()->GetJsType());
- type != nullptr ? Output::Print(_u("type: 0x%p, "), type->GetAddr()) : Output::Print(_u("type: null, "));
- Output::Print(_u("type Set: "));
- Js::EquivalentTypeSet* typeSet = AsJsType()->GetJsTypeSet();
- if (typeSet != nullptr)
- {
- uint16 typeCount = typeSet->GetCount();
- for (uint16 ti = 0; ti < typeCount - 1; ti++)
- {
- Output::Print(_u("0x%p, "), typeSet->GetType(ti));
- }
- Output::Print(_u("0x%p"), typeSet->GetType(typeCount - 1));
- }
- else
- {
- Output::Print(_u("null"));
- }
- }
- else if (IsArrayValueInfo())
- {
- const ArrayValueInfo *const arrayValueInfo = AsArrayValueInfo();
- if (arrayValueInfo->HeadSegmentSym())
- {
- Output::Print(_u(" seg: "));
- arrayValueInfo->HeadSegmentSym()->Dump();
- }
- if (arrayValueInfo->HeadSegmentLengthSym())
- {
- Output::Print(_u(" segLen: "));
- arrayValueInfo->HeadSegmentLengthSym()->Dump();
- }
- if (arrayValueInfo->LengthSym())
- {
- Output::Print(_u(" len: "));
- arrayValueInfo->LengthSym()->Dump();
- }
- }
- if (this->GetSymStore())
- {
- Output::Print(_u("\t\tsym:"));
- this->GetSymStore()->Dump();
- }
- }
- #endif
|