static bool TestSomePointerConversion() { Base base; Derived derived; Maybe<Base*> m1 = Some(&derived); MOZ_RELEASE_ASSERT(m1.isSome()); MOZ_RELEASE_ASSERT(m1); MOZ_RELEASE_ASSERT(*m1 == &derived); auto m2 = ReturnDerivedPointer(); MOZ_RELEASE_ASSERT(m2.isSome()); MOZ_RELEASE_ASSERT(m2); MOZ_RELEASE_ASSERT(*m2 == nullptr); Maybe<Base*> m3 = Some(&base); MOZ_RELEASE_ASSERT(m3.isSome()); MOZ_RELEASE_ASSERT(m3); MOZ_RELEASE_ASSERT(*m3 == &base); auto s1 = Some(&derived); Maybe<Base*> c1(s1); MOZ_RELEASE_ASSERT(c1.isSome()); MOZ_RELEASE_ASSERT(c1); MOZ_RELEASE_ASSERT(*c1 == &derived); ExplicitConstructorBasePointer ecbp(Some(&derived)); return true; }
Maybe<MaybeCheckTDZ> TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name) { if (!ensureCache(bce)) { return Nothing(); } CheckTDZMap::AddPtr p = cache_->lookupForAdd(name); if (p) { return Some(p->value().wrapped); } MaybeCheckTDZ rv = CheckTDZ; for (TDZCheckCache* it = enclosing(); it; it = it->enclosing()) { if (it->cache_) { if (CheckTDZMap::Ptr p2 = it->cache_->lookup(name)) { rv = p2->value(); break; } } } if (!cache_->add(p, name, rv)) { ReportOutOfMemory(bce->cx); return Nothing(); } return Some(rv); }
void UniqueStacks::Stack::AppendFrame(const OnStackFrameKey& aFrame) { // Compute the prefix hash and index before mutating mStack. uint32_t prefixHash = mStack.Hash(); uint32_t prefix = mUniqueStacks.GetOrAddStackIndex(mStack); mStack.mPrefixHash = Some(prefixHash); mStack.mPrefix = Some(prefix); mStack.mFrame = mUniqueStacks.GetOrAddFrameIndex(aFrame); }
static bool TestApply() { // Check that apply handles the 'Nothing' case. gFunctionWasApplied = false; Maybe<BasicValue> mayValue; mayValue.apply(&IncrementTag); mayValue.apply(&AccessValue); mayValue.apply(&IncrementTagBy, 1); mayValue.apply(&AccessValueWithArg, 1); MOZ_RELEASE_ASSERT(!gFunctionWasApplied); // Check that apply handles the 'Some' case. mayValue = Some(BasicValue(1)); mayValue.apply(&IncrementTag); MOZ_RELEASE_ASSERT(gFunctionWasApplied); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2); gFunctionWasApplied = false; mayValue.apply(&AccessValue); MOZ_RELEASE_ASSERT(gFunctionWasApplied); gFunctionWasApplied = false; mayValue.apply(&IncrementTagBy, 2); MOZ_RELEASE_ASSERT(gFunctionWasApplied); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4); gFunctionWasApplied = false; mayValue.apply(&AccessValueWithArg, 1); MOZ_RELEASE_ASSERT(gFunctionWasApplied); // Check that apply works with a const reference. const Maybe<BasicValue>& mayValueCRef = mayValue; gFunctionWasApplied = false; mayValueCRef.apply(&AccessValue); MOZ_RELEASE_ASSERT(gFunctionWasApplied); gFunctionWasApplied = false; mayValueCRef.apply(&AccessValueWithArg, 1); MOZ_RELEASE_ASSERT(gFunctionWasApplied); // Check that apply works with functors. IncrementTagFunctor tagIncrementer; MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); mayValue = Some(BasicValue(1)); mayValue.apply(tagIncrementer); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2); MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); mayValue.apply(tagIncrementer, BasicValue(2)); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4); MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == true); BasicValue incrementBy(3); mayValue.apply(tagIncrementer, incrementBy); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 7); MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == false); return true; }
static bool TestMap() { // Check that map handles the 'Nothing' case. Maybe<BasicValue> mayValue; MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Nothing()); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValue.map(&TimesTwo))>::value, "map(TimesTwo) should return a Maybe<int>"); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Nothing()); // Check that map handles the 'Some' case. mayValue = Some(BasicValue(2)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Some(4)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Some(4)); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1); mayValue = Some(BasicValue(2)); // Check that map works with a const reference. mayValue->SetTag(2); const Maybe<BasicValue>& mayValueCRef = mayValue; MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesTwo) == Some(4)); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValueCRef.map(&TimesTwo))>::value, "map(TimesTwo) should return a Maybe<int>"); // Check that map works with functors. MultiplyTagFunctor tagMultiplier; MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier) == Some(4)); MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); // Check that map works with lambda expressions. int two = 2; mayValue = Some(BasicValue(2)); Maybe<int> mappedValue = mayValue.map([&](const BasicValue& aVal) { return aVal.GetTag() * two; }); MOZ_RELEASE_ASSERT(mappedValue == Some(4)); mappedValue = mayValue.map([=](const BasicValue& aVal) { return aVal.GetTag() * two; }); MOZ_RELEASE_ASSERT(mappedValue == Some(4)); mappedValue = mayValueCRef.map([&](const BasicValue& aVal) { return aVal.GetTag() * two; }); MOZ_RELEASE_ASSERT(mappedValue == Some(4)); return true; }
static bool TestMap() { // Check that map handles the 'Nothing' case. Maybe<BasicValue> mayValue; MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Nothing()); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValue.map(&TimesTwo))>::value, "map(TimesTwo) should return a Maybe<int>"); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Nothing()); MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Nothing()); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValue.map(&TimesNum, 3))>::value, "map(TimesNum, 3) should return a Maybe<int>"); MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Nothing()); // Check that map handles the 'Some' case. mayValue = Some(BasicValue(2)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Some(4)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Some(4)); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1); mayValue = Some(BasicValue(2)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Some(6)); MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Some(6)); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1); // Check that map works with a const reference. mayValue->SetTag(2); const Maybe<BasicValue>& mayValueCRef = mayValue; MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesTwo) == Some(4)); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValueCRef.map(&TimesTwo))>::value, "map(TimesTwo) should return a Maybe<int>"); MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesNum, 3) == Some(6)); static_assert(IsSame<Maybe<int>, DECLTYPE(mayValueCRef.map(&TimesNum, 3))>::value, "map(TimesNum, 3) should return a Maybe<int>"); // Check that map works with functors. // XXX(seth): Support for functors will be added in bug 1054115; it had to be // ripped out temporarily because of incompatibilities with GCC 4.4. /* MultiplyTagFunctor tagMultiplier; MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier) == Some(4)); MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, BasicValue(3)) == Some(6)); MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == true); BasicValue multiplyBy(3); MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, multiplyBy) == Some(6)); MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == false); */ return true; }
static bool TestApply() { // Check that apply handles the 'Nothing' case. gFunctionWasApplied = false; Maybe<BasicValue> mayValue; mayValue.apply(&IncrementTag); mayValue.apply(&AccessValue); MOZ_RELEASE_ASSERT(!gFunctionWasApplied); // Check that apply handles the 'Some' case. mayValue = Some(BasicValue(1)); mayValue.apply(&IncrementTag); MOZ_RELEASE_ASSERT(gFunctionWasApplied); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2); gFunctionWasApplied = false; mayValue.apply(&AccessValue); MOZ_RELEASE_ASSERT(gFunctionWasApplied); // Check that apply works with a const reference. const Maybe<BasicValue>& mayValueCRef = mayValue; gFunctionWasApplied = false; mayValueCRef.apply(&AccessValue); MOZ_RELEASE_ASSERT(gFunctionWasApplied); // Check that apply works with functors. IncrementTagFunctor tagIncrementer; MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); mayValue = Some(BasicValue(1)); mayValue.apply(tagIncrementer); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2); MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed); // Check that apply works with lambda expressions. int32_t two = 2; gFunctionWasApplied = false; mayValue = Some(BasicValue(2)); mayValue.apply([&](BasicValue& aVal) { aVal.SetTag(aVal.GetTag() * two); }); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4); mayValue.apply([=](BasicValue& aVal) { aVal.SetTag(aVal.GetTag() * two); }); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 8); mayValueCRef.apply([&](const BasicValue& aVal) { gFunctionWasApplied = true; }); MOZ_RELEASE_ASSERT(gFunctionWasApplied == true); return true; }
static bool TestComparisonOperators() { Maybe<BasicValue> nothingValue = Nothing(); Maybe<BasicValue> anotherNothingValue = Nothing(); Maybe<BasicValue> oneValue = Some(BasicValue(1)); Maybe<BasicValue> anotherOneValue = Some(BasicValue(1)); Maybe<BasicValue> twoValue = Some(BasicValue(2)); // Check equality. MOZ_RELEASE_ASSERT(nothingValue == anotherNothingValue); MOZ_RELEASE_ASSERT(oneValue == anotherOneValue); // Check inequality. MOZ_RELEASE_ASSERT(nothingValue != oneValue); MOZ_RELEASE_ASSERT(oneValue != nothingValue); MOZ_RELEASE_ASSERT(oneValue != twoValue); // Check '<'. MOZ_RELEASE_ASSERT(nothingValue < oneValue); MOZ_RELEASE_ASSERT(oneValue < twoValue); // Check '<='. MOZ_RELEASE_ASSERT(nothingValue <= anotherNothingValue); MOZ_RELEASE_ASSERT(nothingValue <= oneValue); MOZ_RELEASE_ASSERT(oneValue <= oneValue); MOZ_RELEASE_ASSERT(oneValue <= twoValue); // Check '>'. MOZ_RELEASE_ASSERT(oneValue > nothingValue); MOZ_RELEASE_ASSERT(twoValue > oneValue); // Check '>='. MOZ_RELEASE_ASSERT(nothingValue >= anotherNothingValue); MOZ_RELEASE_ASSERT(oneValue >= nothingValue); MOZ_RELEASE_ASSERT(oneValue >= oneValue); MOZ_RELEASE_ASSERT(twoValue >= oneValue); return true; }
static bool TestSomeNullptrConversion() { Maybe<int*> m1 = Some(nullptr); MOZ_RELEASE_ASSERT(m1.isSome()); MOZ_RELEASE_ASSERT(m1); MOZ_RELEASE_ASSERT(!*m1); auto m2 = ReturnSomeNullptr(); MOZ_RELEASE_ASSERT(m2.isSome()); MOZ_RELEASE_ASSERT(m2); MOZ_RELEASE_ASSERT(!*m2); Maybe<decltype(nullptr)> m3 = Some(nullptr); MOZ_RELEASE_ASSERT(m3.isSome()); MOZ_RELEASE_ASSERT(m3); MOZ_RELEASE_ASSERT(*m3 == nullptr); D d(Some(nullptr)); return true; }
static bool TestFunctionalAccessors() { BasicValue value(9); sStaticBasicValue = new BasicValue(9); // Check that the 'some' case of functional accessors works. Maybe<BasicValue> someValue = Some(BasicValue(3)); MOZ_RELEASE_ASSERT(someValue.valueOr(value) == BasicValue(3)); static_assert(IsSame<BasicValue, DECLTYPE(someValue.valueOr(value))>::value, "valueOr should return a BasicValue"); MOZ_RELEASE_ASSERT(someValue.valueOrFrom(&MakeBasicValue) == BasicValue(3)); static_assert(IsSame<BasicValue, DECLTYPE(someValue.valueOrFrom(&MakeBasicValue))>::value, "valueOrFrom should return a BasicValue"); MOZ_RELEASE_ASSERT(someValue.ptrOr(&value) != &value); static_assert(IsSame<BasicValue*, DECLTYPE(someValue.ptrOr(&value))>::value, "ptrOr should return a BasicValue*"); MOZ_RELEASE_ASSERT(*someValue.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(3)); static_assert(IsSame<BasicValue*, DECLTYPE(someValue.ptrOrFrom(&MakeBasicValuePtr))>::value, "ptrOrFrom should return a BasicValue*"); MOZ_RELEASE_ASSERT(someValue.refOr(value) == BasicValue(3)); static_assert(IsSame<BasicValue&, DECLTYPE(someValue.refOr(value))>::value, "refOr should return a BasicValue&"); MOZ_RELEASE_ASSERT(someValue.refOrFrom(&MakeBasicValueRef) == BasicValue(3)); static_assert(IsSame<BasicValue&, DECLTYPE(someValue.refOrFrom(&MakeBasicValueRef))>::value, "refOrFrom should return a BasicValue&"); // Check that the 'some' case works through a const reference. const Maybe<BasicValue>& someValueCRef = someValue; MOZ_RELEASE_ASSERT(someValueCRef.valueOr(value) == BasicValue(3)); static_assert(IsSame<BasicValue, DECLTYPE(someValueCRef.valueOr(value))>::value, "valueOr should return a BasicValue"); MOZ_RELEASE_ASSERT(someValueCRef.valueOrFrom(&MakeBasicValue) == BasicValue(3)); static_assert(IsSame<BasicValue, DECLTYPE(someValueCRef.valueOrFrom(&MakeBasicValue))>::value, "valueOrFrom should return a BasicValue"); MOZ_RELEASE_ASSERT(someValueCRef.ptrOr(&value) != &value); static_assert(IsSame<const BasicValue*, DECLTYPE(someValueCRef.ptrOr(&value))>::value, "ptrOr should return a const BasicValue*"); MOZ_RELEASE_ASSERT(*someValueCRef.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(3)); static_assert(IsSame<const BasicValue*, DECLTYPE(someValueCRef.ptrOrFrom(&MakeBasicValuePtr))>::value, "ptrOrFrom should return a const BasicValue*"); MOZ_RELEASE_ASSERT(someValueCRef.refOr(value) == BasicValue(3)); static_assert(IsSame<const BasicValue&, DECLTYPE(someValueCRef.refOr(value))>::value, "refOr should return a const BasicValue&"); MOZ_RELEASE_ASSERT(someValueCRef.refOrFrom(&MakeBasicValueRef) == BasicValue(3)); static_assert(IsSame<const BasicValue&, DECLTYPE(someValueCRef.refOrFrom(&MakeBasicValueRef))>::value, "refOrFrom should return a const BasicValue&"); // Check that the 'none' case of functional accessors works. Maybe<BasicValue> noneValue; MOZ_RELEASE_ASSERT(noneValue.valueOr(value) == BasicValue(9)); static_assert(IsSame<BasicValue, DECLTYPE(noneValue.valueOr(value))>::value, "valueOr should return a BasicValue"); MOZ_RELEASE_ASSERT(noneValue.valueOrFrom(&MakeBasicValue) == BasicValue(9)); static_assert(IsSame<BasicValue, DECLTYPE(noneValue.valueOrFrom(&MakeBasicValue))>::value, "valueOrFrom should return a BasicValue"); MOZ_RELEASE_ASSERT(noneValue.ptrOr(&value) == &value); static_assert(IsSame<BasicValue*, DECLTYPE(noneValue.ptrOr(&value))>::value, "ptrOr should return a BasicValue*"); MOZ_RELEASE_ASSERT(*noneValue.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(9)); static_assert(IsSame<BasicValue*, DECLTYPE(noneValue.ptrOrFrom(&MakeBasicValuePtr))>::value, "ptrOrFrom should return a BasicValue*"); MOZ_RELEASE_ASSERT(noneValue.refOr(value) == BasicValue(9)); static_assert(IsSame<BasicValue&, DECLTYPE(noneValue.refOr(value))>::value, "refOr should return a BasicValue&"); MOZ_RELEASE_ASSERT(noneValue.refOrFrom(&MakeBasicValueRef) == BasicValue(9)); static_assert(IsSame<BasicValue&, DECLTYPE(noneValue.refOrFrom(&MakeBasicValueRef))>::value, "refOrFrom should return a BasicValue&"); // Check that the 'none' case works through a const reference. const Maybe<BasicValue>& noneValueCRef = noneValue; MOZ_RELEASE_ASSERT(noneValueCRef.valueOr(value) == BasicValue(9)); static_assert(IsSame<BasicValue, DECLTYPE(noneValueCRef.valueOr(value))>::value, "valueOr should return a BasicValue"); MOZ_RELEASE_ASSERT(noneValueCRef.valueOrFrom(&MakeBasicValue) == BasicValue(9)); static_assert(IsSame<BasicValue, DECLTYPE(noneValueCRef.valueOrFrom(&MakeBasicValue))>::value, "valueOrFrom should return a BasicValue"); MOZ_RELEASE_ASSERT(noneValueCRef.ptrOr(&value) == &value); static_assert(IsSame<const BasicValue*, DECLTYPE(noneValueCRef.ptrOr(&value))>::value, "ptrOr should return a const BasicValue*"); MOZ_RELEASE_ASSERT(*noneValueCRef.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(9)); static_assert(IsSame<const BasicValue*, DECLTYPE(noneValueCRef.ptrOrFrom(&MakeBasicValuePtr))>::value, "ptrOrFrom should return a const BasicValue*"); MOZ_RELEASE_ASSERT(noneValueCRef.refOr(value) == BasicValue(9)); static_assert(IsSame<const BasicValue&, DECLTYPE(noneValueCRef.refOr(value))>::value, "refOr should return a const BasicValue&"); MOZ_RELEASE_ASSERT(noneValueCRef.refOrFrom(&MakeBasicValueRef) == BasicValue(9)); static_assert(IsSame<const BasicValue&, DECLTYPE(noneValueCRef.refOrFrom(&MakeBasicValueRef))>::value, "refOrFrom should return a const BasicValue&"); // Clean up so the undestroyed objects count stays accurate. delete sStaticBasicValue; sStaticBasicValue = nullptr; return true; }
static bool TestCopyAndMove() { // Check that we get moves when possible for types that can support both moves // and copies. Maybe<BasicValue> mayBasicValue = Some(BasicValue(1)); MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveConstructed); MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 1); mayBasicValue = Some(BasicValue(2)); MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveAssigned); MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 2); mayBasicValue.reset(); mayBasicValue.emplace(BasicValue(3)); MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveConstructed); MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 3); // Check that we get copies when moves aren't possible. Maybe<BasicValue> mayBasicValue2 = Some(*mayBasicValue); MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyConstructed); MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 3); mayBasicValue->SetTag(4); mayBasicValue2 = mayBasicValue; // This test should work again when we fix bug 1052940. //MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyAssigned); MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 4); mayBasicValue->SetTag(5); mayBasicValue2.reset(); mayBasicValue2.emplace(*mayBasicValue); MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyConstructed); MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 5); // Check that Move() works. (Another sanity check for move support.) Maybe<BasicValue> mayBasicValue3 = Some(Move(*mayBasicValue)); MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMoveConstructed); MOZ_RELEASE_ASSERT(mayBasicValue3->GetTag() == 5); MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMovedFrom); mayBasicValue2->SetTag(6); mayBasicValue3 = Some(Move(*mayBasicValue2)); MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMoveAssigned); MOZ_RELEASE_ASSERT(mayBasicValue3->GetTag() == 6); MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasMovedFrom); Maybe<BasicValue> mayBasicValue4; mayBasicValue4.emplace(Move(*mayBasicValue3)); MOZ_RELEASE_ASSERT(mayBasicValue4->GetStatus() == eWasMoveConstructed); MOZ_RELEASE_ASSERT(mayBasicValue4->GetTag() == 6); MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMovedFrom); // Check that we always get copies for types that don't support moves. // XXX(seth): These tests fail but probably shouldn't. For now we'll just // consider using Maybe with types that allow copies but have deleted or // private move constructors, or which do not support copy assignment, to // be supported only to the extent that we need for existing code to work. // These tests should work again when we fix bug 1052940. /* Maybe<UnmovableValue> mayUnmovableValue = Some(UnmovableValue()); MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyConstructed); mayUnmovableValue = Some(UnmovableValue()); MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyAssigned); mayUnmovableValue.reset(); mayUnmovableValue.emplace(UnmovableValue()); MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyConstructed); */ // Check that types that only support moves, but not copies, work. Maybe<UncopyableValue> mayUncopyableValue = Some(UncopyableValue()); MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveConstructed); mayUncopyableValue = Some(UncopyableValue()); MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveAssigned); mayUncopyableValue.reset(); mayUncopyableValue.emplace(UncopyableValue()); MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveConstructed); // Check that types that support neither moves or copies work. Maybe<UncopyableUnmovableValue> mayUncopyableUnmovableValue; mayUncopyableUnmovableValue.emplace(); MOZ_RELEASE_ASSERT(mayUncopyableUnmovableValue->GetStatus() == eWasDefaultConstructed); mayUncopyableUnmovableValue.reset(); mayUncopyableUnmovableValue.emplace(0); MOZ_RELEASE_ASSERT(mayUncopyableUnmovableValue->GetStatus() == eWasConstructed); return true; }
static bool TestBasicFeatures() { // Check that a Maybe<T> is initialized to Nothing. Maybe<BasicValue> mayValue; static_assert(IsSame<BasicValue, DECLTYPE(mayValue)::ValueType>::value, "Should have BasicValue ValueType"); MOZ_RELEASE_ASSERT(!mayValue); MOZ_RELEASE_ASSERT(!mayValue.isSome()); MOZ_RELEASE_ASSERT(mayValue.isNothing()); // Check that emplace() default constructs and the accessors work. mayValue.emplace(); MOZ_RELEASE_ASSERT(mayValue); MOZ_RELEASE_ASSERT(mayValue.isSome()); MOZ_RELEASE_ASSERT(!mayValue.isNothing()); MOZ_RELEASE_ASSERT(*mayValue == BasicValue()); MOZ_RELEASE_ASSERT(mayValue.value() == BasicValue()); static_assert(IsSame<BasicValue, DECLTYPE(mayValue.value())>::value, "value() should return a BasicValue"); MOZ_RELEASE_ASSERT(mayValue.ref() == BasicValue()); static_assert(IsSame<BasicValue&, DECLTYPE(mayValue.ref())>::value, "ref() should return a BasicValue&"); MOZ_RELEASE_ASSERT(mayValue.ptr() != nullptr); static_assert(IsSame<BasicValue*, DECLTYPE(mayValue.ptr())>::value, "ptr() should return a BasicValue*"); MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasDefaultConstructed); // Check that reset() works. mayValue.reset(); MOZ_RELEASE_ASSERT(!mayValue); MOZ_RELEASE_ASSERT(!mayValue.isSome()); MOZ_RELEASE_ASSERT(mayValue.isNothing()); // Check that emplace(T1) calls the correct constructor. mayValue.emplace(1); MOZ_RELEASE_ASSERT(mayValue); MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasConstructed); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1); mayValue.reset(); MOZ_RELEASE_ASSERT(!mayValue); // Check that Some() and Nothing() work. mayValue = Some(BasicValue(2)); MOZ_RELEASE_ASSERT(mayValue); MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasMoveConstructed); MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2); mayValue = Nothing(); MOZ_RELEASE_ASSERT(!mayValue); // Check that the accessors work through a const ref. mayValue.emplace(); const Maybe<BasicValue>& mayValueCRef = mayValue; MOZ_RELEASE_ASSERT(mayValueCRef); MOZ_RELEASE_ASSERT(mayValueCRef.isSome()); MOZ_RELEASE_ASSERT(!mayValueCRef.isNothing()); MOZ_RELEASE_ASSERT(*mayValueCRef == BasicValue()); MOZ_RELEASE_ASSERT(mayValueCRef.value() == BasicValue()); static_assert(IsSame<BasicValue, DECLTYPE(mayValueCRef.value())>::value, "value() should return a BasicValue"); MOZ_RELEASE_ASSERT(mayValueCRef.ref() == BasicValue()); static_assert(IsSame<const BasicValue&, DECLTYPE(mayValueCRef.ref())>::value, "ref() should return a const BasicValue&"); MOZ_RELEASE_ASSERT(mayValueCRef.ptr() != nullptr); static_assert(IsSame<const BasicValue*, DECLTYPE(mayValueCRef.ptr())>::value, "ptr() should return a const BasicValue*"); MOZ_RELEASE_ASSERT(mayValueCRef->GetStatus() == eWasDefaultConstructed); mayValue.reset(); return true; }
Maybe<uint64_t> nsStringInputStream::ExpectedSerializedLength() { return Some(static_cast<uint64_t>(Length())); }
static Maybe<Base*> ReturnDerivedPointer() { Derived* d = nullptr; return Some(d); }
static Maybe<int*> ReturnSomeNullptr() { return Some(nullptr); }
void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter, int aThreadId, float aSinceTime, JSRuntime* aRuntime, UniqueStacks& aUniqueStacks) { Maybe<ProfileSample> sample; int readPos = mReadPos; int currentThreadID = -1; Maybe<float> currentTime; UniquePtr<char[]> tagBuff = MakeUnique<char[]>(DYNAMIC_MAX_STRING); while (readPos != mWritePos) { ProfileEntry entry = mEntries[readPos]; if (entry.mTagName == 'T') { currentThreadID = entry.mTagInt; currentTime.reset(); int readAheadPos = (readPos + 1) % mEntrySize; if (readAheadPos != mWritePos) { ProfileEntry readAheadEntry = mEntries[readAheadPos]; if (readAheadEntry.mTagName == 't') { currentTime = Some(readAheadEntry.mTagFloat); } } } if (currentThreadID == aThreadId && (currentTime.isNothing() || *currentTime >= aSinceTime)) { switch (entry.mTagName) { case 'r': if (sample.isSome()) { sample->mResponsiveness = Some(entry.mTagFloat); } break; case 'p': if (sample.isSome()) { sample->mPower = Some(entry.mTagFloat); } break; case 'R': if (sample.isSome()) { sample->mRSS = Some(entry.mTagFloat); } break; case 'U': if (sample.isSome()) { sample->mUSS = Some(entry.mTagFloat); } break; case 'f': if (sample.isSome()) { sample->mFrameNumber = Some(entry.mTagInt); } break; case 's': { // end the previous sample if there was one if (sample.isSome()) { WriteSample(aWriter, *sample); sample.reset(); } // begin the next sample sample.emplace(); sample->mTime = currentTime; // Seek forward through the entire sample, looking for frames // this is an easier approach to reason about than adding more // control variables and cases to the loop that goes through the buffer once UniqueStacks::Stack stack = aUniqueStacks.BeginStack(UniqueStacks::OnStackFrameKey("(root)")); int framePos = (readPos + 1) % mEntrySize; ProfileEntry frame = mEntries[framePos]; while (framePos != mWritePos && frame.mTagName != 's' && frame.mTagName != 'T') { int incBy = 1; frame = mEntries[framePos]; // Read ahead to the next tag, if it's a 'd' tag process it now const char* tagStringData = frame.mTagData; int readAheadPos = (framePos + 1) % mEntrySize; // Make sure the string is always null terminated if it fills up // DYNAMIC_MAX_STRING-2 tagBuff[DYNAMIC_MAX_STRING-1] = '\0'; if (readAheadPos != mWritePos && mEntries[readAheadPos].mTagName == 'd') { tagStringData = processDynamicTag(framePos, &incBy, tagBuff.get()); } // Write one frame. It can have either // 1. only location - 'l' containing a memory address // 2. location and line number - 'c' followed by 'd's, // an optional 'n' and an optional 'y' // 3. a JIT return address - 'j' containing native code address if (frame.mTagName == 'l') { // Bug 753041 // We need a double cast here to tell GCC that we don't want to sign // extend 32-bit addresses starting with 0xFXXXXXX. unsigned long long pc = (unsigned long long)(uintptr_t)frame.mTagPtr; snprintf(tagBuff.get(), DYNAMIC_MAX_STRING, "%#llx", pc); stack.AppendFrame(UniqueStacks::OnStackFrameKey(tagBuff.get())); } else if (frame.mTagName == 'c') { UniqueStacks::OnStackFrameKey frameKey(tagStringData); readAheadPos = (framePos + incBy) % mEntrySize; if (readAheadPos != mWritePos && mEntries[readAheadPos].mTagName == 'n') { frameKey.mLine = Some((unsigned) mEntries[readAheadPos].mTagInt); incBy++; } readAheadPos = (framePos + incBy) % mEntrySize; if (readAheadPos != mWritePos && mEntries[readAheadPos].mTagName == 'y') { frameKey.mCategory = Some((unsigned) mEntries[readAheadPos].mTagInt); incBy++; } stack.AppendFrame(frameKey); } else if (frame.mTagName == 'J') { // A JIT frame may expand to multiple frames due to inlining. void* pc = frame.mTagPtr; unsigned depth = aUniqueStacks.LookupJITFrameDepth(pc); if (depth == 0) { StreamJSFramesOp framesOp(pc, stack); JS::ForEachProfiledFrame(aRuntime, pc, framesOp); aUniqueStacks.AddJITFrameDepth(pc, framesOp.depth()); } else { for (unsigned i = 0; i < depth; i++) { UniqueStacks::OnStackFrameKey inlineFrameKey(pc, i); stack.AppendFrame(inlineFrameKey); } } } framePos = (framePos + incBy) % mEntrySize; } sample->mStack = stack.GetOrAddIndex(); break; } } } readPos = (readPos + 1) % mEntrySize; } if (sample.isSome()) { WriteSample(aWriter, *sample); } }