diff options
Diffstat (limited to 'src/mongo/db/exec/sbe/vm/vm.cpp')
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm.cpp | 672 |
1 files changed, 261 insertions, 411 deletions
diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp index 7a6790380ea..193d0a0e437 100644 --- a/src/mongo/db/exec/sbe/vm/vm.cpp +++ b/src/mongo/db/exec/sbe/vm/vm.cpp @@ -158,25 +158,15 @@ int Instruction::stackOffset[Instruction::Tags::lastInstruction] = { 0, // applyClassicMatcher }; -namespace { -template <typename T> -T readFromMemory(const uint8_t* ptr) noexcept { - static_assert(!IsEndian<T>::value); - - T val; - memcpy(&val, ptr, sizeof(T)); - return val; +void ByteCode::growAndResize() noexcept { + invariant(_argStackTop == _argStackEnd); + auto oldSize = (_argStackEnd - _argStack) / sizeOfElement; + auto newSize = oldSize * 3 / 2; + _argStack = reinterpret_cast<uint8_t*>(mongoRealloc(_argStack, newSize * sizeOfElement)); + _argStackEnd = _argStack + newSize * sizeOfElement; + _argStackTop = _argStack + oldSize * sizeOfElement; } -template <typename T> -size_t writeToMemory(uint8_t* ptr, const T val) noexcept { - static_assert(!IsEndian<T>::value); - - memcpy(ptr, &val, sizeof(T)); - return sizeof(T); -} -} // namespace - std::string CodeFragment::toString() const { std::ostringstream ss; auto pcPointer = _instrs.data(); @@ -720,52 +710,10 @@ void CodeFragment::appendJumpNothing(int jumpOffset) { offset += writeToMemory(offset, jumpOffset); } -void ByteCode::Stack::growAndResize(size_t newSize) { - auto currentCapacity = capacity(); - if (newSize <= currentCapacity) { - _size = newSize; - return; - } - - auto newCapacity = newSize; - if (newCapacity > kMaxCapacity) { - uasserted(6040901, - str::stream() << "Requested capacity of " << newCapacity - << " elements exceeds the maximum capacity of " << kMaxCapacity); - return; - } - - if (currentCapacity >= kMaxCapacity / 2) { - newCapacity = kMaxCapacity; - } else if (2 * currentCapacity > newCapacity) { - newCapacity = 2 * currentCapacity; - } - - try { - auto numSegments = (_size + ElementsPerSegment - 1) / ElementsPerSegment; - auto numNewSegments = (newCapacity + ElementsPerSegment - 1) / ElementsPerSegment; - newCapacity = numNewSegments * ElementsPerSegment; - - auto newSegments = std::make_unique<StackSegment[]>(numNewSegments); - - if (_segments.get() != nullptr && numSegments > 0) { - memcpy(newSegments.get(), _segments.get(), numSegments * sizeof(StackSegment)); - } - - _segments = std::move(newSegments); - _capacity = newCapacity; - _size = newSize; - } catch (std::bad_alloc&) { - uasserted(6040902, - str::stream() << "Unable to allocate requested capacity of " << newCapacity - << " elements"); - } -} - -std::tuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTags objTag, - value::Value objValue, - value::TypeTags fieldTag, - value::Value fieldValue) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTags objTag, + value::Value objValue, + value::TypeTags fieldTag, + value::Value fieldValue) { if (!value::isString(fieldTag)) { return {false, value::TypeTags::Nothing, 0}; } @@ -775,9 +723,9 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTa return getField(objTag, objValue, fieldStr); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTags objTag, - value::Value objValue, - StringData fieldStr) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTags objTag, + value::Value objValue, + StringData fieldStr) { if (MONGO_unlikely(failOnPoisonedFieldLookup.shouldFail())) { uassert(4623399, "Lookup of $POISON", fieldStr != "POISON"); } @@ -804,10 +752,10 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::getField(value::TypeTa return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::getElement(value::TypeTags arrTag, - value::Value arrValue, - value::TypeTags idxTag, - value::Value idxValue) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::getElement(value::TypeTags arrTag, + value::Value arrValue, + value::TypeTags idxTag, + value::Value idxValue) { // We need to ensure that 'size_t' is wide enough to store 32-bit index. static_assert(sizeof(size_t) >= sizeof(int32_t), "size_t must be at least 32-bits"); @@ -898,7 +846,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::getElement(value::Type } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::getFieldOrElement( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::getFieldOrElement( value::TypeTags objTag, value::Value objValue, value::TypeTags fieldTag, @@ -1057,13 +1005,14 @@ void ByteCode::traverseFInArray(const CodeFragment* code, int64_t position, bool // Transfer the ownership to the lambda pushStack(ownInput, tagInput, valInput); input.reset(); - return runLambdaInternal(code, position); + runLambdaInternal(code, position); + return; } pushStack(false, value::TypeTags::Boolean, value::bitcastFrom<bool>(false)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::setField() { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::setField() { auto [newOwn, newTag, newVal] = moveFromStack(0); auto [fieldOwn, fieldTag, fieldVal] = getFromStack(1); // Consider using a moveFromStack optimization. @@ -1164,8 +1113,8 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::setField() { return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::getArraySize(value::TypeTags tag, - value::Value val) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::getArraySize(value::TypeTags tag, + value::Value val) { size_t result = 0; switch (tag) { @@ -1190,10 +1139,10 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::getArraySize(value::Ty return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggSum(value::TypeTags accTag, - value::Value accValue, - value::TypeTags fieldTag, - value::Value fieldValue) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::aggSum(value::TypeTags accTag, + value::Value accValue, + value::TypeTags fieldTag, + value::Value fieldValue) { // Skip aggregation step if we don't have the input. if (fieldTag == value::TypeTags::Nothing) { auto [tag, val] = value::copyValue(accTag, accValue); @@ -1209,7 +1158,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggSum(value::TypeTags return genericAdd(accTag, accValue, fieldTag, fieldValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggDoubleDoubleSum( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggDoubleDoubleSum( ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(1); @@ -1244,7 +1193,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggDoubleDouble // This function is necessary because 'aggDoubleDoubleSum()' result is 'Array' type but we need // to produce a scalar value out of it. -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSumFinalize( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSumFinalize( ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(0); auto arr = value::getArrayView(fieldValue); @@ -1314,7 +1263,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoublePartialSumFinalize( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoublePartialSumFinalize( ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(0); @@ -1391,7 +1340,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoublePar return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggStdDev(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggStdDev(ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(1); // Move the incoming accumulator state from the stack. Given that we are now the owner of the // state we are free to do any in-place update as we see fit. @@ -1420,25 +1369,24 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAggStdDev(Arity return {true, accTag, accValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinStdDevPopFinalize( - ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinStdDevPopFinalize(ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(0); return aggStdDevFinalizeImpl(fieldValue, false /* isSamp */); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinStdDevSampFinalize( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinStdDevSampFinalize( ArityType arity) { auto [_, fieldTag, fieldValue] = getFromStack(0); return aggStdDevFinalizeImpl(fieldValue, true /* isSamp */); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMin(value::TypeTags accTag, - value::Value accValue, - value::TypeTags fieldTag, - value::Value fieldValue, - CollatorInterface* collator) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::aggMin(value::TypeTags accTag, + value::Value accValue, + value::TypeTags fieldTag, + value::Value fieldValue, + CollatorInterface* collator) { // Skip aggregation step if we don't have the input. if (fieldTag == value::TypeTags::Nothing) { auto [tag, val] = value::copyValue(accTag, accValue); @@ -1463,11 +1411,11 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMin(value::TypeTags } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMax(value::TypeTags accTag, - value::Value accValue, - value::TypeTags fieldTag, - value::Value fieldValue, - CollatorInterface* collator) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::aggMax(value::TypeTags accTag, + value::Value accValue, + value::TypeTags fieldTag, + value::Value fieldValue, + CollatorInterface* collator) { // Skip aggregation step if we don't have the input. if (fieldTag == value::TypeTags::Nothing) { auto [tag, val] = value::copyValue(accTag, accValue); @@ -1491,10 +1439,10 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggMax(value::TypeTags } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggFirst(value::TypeTags accTag, - value::Value accValue, - value::TypeTags fieldTag, - value::Value fieldValue) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::aggFirst(value::TypeTags accTag, + value::Value accValue, + value::TypeTags fieldTag, + value::Value fieldValue) { // Skip aggregation step if we don't have the input. if (fieldTag == value::TypeTags::Nothing) { auto [tag, val] = value::copyValue(accTag, accValue); @@ -1512,10 +1460,10 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggFirst(value::TypeTa return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::aggLast(value::TypeTags accTag, - value::Value accValue, - value::TypeTags fieldTag, - value::Value fieldValue) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::aggLast(value::TypeTags accTag, + value::Value accValue, + value::TypeTags fieldTag, + value::Value fieldValue) { // Skip aggregation step if we don't have the input. if (fieldTag == value::TypeTags::Nothing) { auto [tag, val] = value::copyValue(accTag, accValue); @@ -1539,7 +1487,7 @@ bool hasSeparatorAt(size_t idx, StringData input, StringData separator) { input.substr(idx, separator.size()) == separator; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSplit(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSplit(ArityType arity) { auto [ownedSeparator, tagSeparator, valSeparator] = getFromStack(1); auto [ownedInput, tagInput, valInput] = getFromStack(0); @@ -1573,7 +1521,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSplit(ArityType return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDropFields(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDropFields(ArityType arity) { auto [ownedSeparator, tagInObj, valInObj] = getFromStack(0); // We operate only on objects. @@ -1630,7 +1578,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDropFields(Arit return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArray(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArray(ArityType arity) { auto [tag, val] = value::makeNewArray(); value::ValueGuard guard{tag, val}; @@ -1649,7 +1597,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArray(ArityT return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeepFields(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeepFields(ArityType arity) { auto [ownedInObj, tagInObj, valInObj] = getFromStack(0); // We operate only on objects. @@ -1705,8 +1653,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeepFields(Arit return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArrayFromRange( - ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArrayFromRange(ArityType arity) { auto [tag, val] = value::makeNewArray(); value::ValueGuard guard{tag, val}; @@ -1754,7 +1701,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewArrayFromRan return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewObj(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewObj(ArityType arity) { std::vector<value::TypeTags> typeTags; std::vector<value::Value> values; std::vector<std::string> names; @@ -1797,8 +1744,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewObj(ArityTyp return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeyStringToString( - ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeyStringToString(ArityType arity) { auto [owned, tagInKey, valInKey] = getFromStack(0); // We operate only on keys. @@ -1813,7 +1759,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinKeyStringToStri return {true, tagStr, valStr}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericNewKeyString( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericNewKeyString( ArityType arity, CollatorInterface* collator) { auto [_, tagVersion, valVersion] = getFromStack(0); auto [__, tagOrdering, valOrdering] = getFromStack(1); @@ -2002,14 +1948,14 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::genericNewKeyString( value::bitcastFrom<KeyString::Value*>(new KeyString::Value(kb.release()))}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewKeyString(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinNewKeyString(ArityType arity) { tassert(6333000, str::stream() << "Unsupported number of arguments passed to ks(): " << arity, arity >= 3 && arity <= Ordering::kMaxCompoundIndexKeys + 3); return genericNewKeyString(arity); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollNewKeyString(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollNewKeyString(ArityType arity) { tassert(6511500, str::stream() << "Unsupported number of arguments passed to collKs(): " << arity, arity >= 4 && arity <= Ordering::kMaxCompoundIndexKeys + 4); @@ -2022,7 +1968,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollNewKeyStrin return genericNewKeyString(arity - 1u, collator); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAbs(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAbs(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2030,7 +1976,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAbs(ArityType a return genericAbs(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCeil(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCeil(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2038,7 +1984,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCeil(ArityType return genericCeil(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinFloor(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinFloor(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2046,7 +1992,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinFloor(ArityType return genericFloor(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTrunc(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTrunc(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2054,7 +2000,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTrunc(ArityType return genericTrunc(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinExp(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinExp(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2062,7 +2008,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinExp(ArityType a return genericExp(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinLn(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinLn(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2070,7 +2016,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinLn(ArityType ar return genericLn(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinLog10(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinLog10(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2078,7 +2024,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinLog10(ArityType return genericLog10(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSqrt(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSqrt(ArityType arity) { invariant(arity == 1); auto [_, tagOperand, valOperand] = getFromStack(0); @@ -2086,7 +2032,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSqrt(ArityType return genericSqrt(tagOperand, valOperand); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArray(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArray(ArityType arity) { auto [ownAgg, tagAgg, valAgg] = getFromStack(0); auto [tagField, valField] = moveOwnedFromStack(1); value::ValueGuard guardField{tagField, valField}; @@ -2114,7 +2060,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArray(Arit // The value being accumulated is an SBE array that contains an integer and the accumulated array, // where the integer is the total size in bytes of the elements in the array. -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArrayCapped(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArrayCapped(ArityType arity) { auto [ownArr, tagArr, valArr] = getFromStack(0); auto [tagNewElem, valNewElem] = moveOwnedFromStack(1); value::ValueGuard guardNewElem{tagNewElem, valNewElem}; @@ -2181,7 +2127,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToArrayCappe return {ownArr, tagArr, valArr}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinMergeObjects(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinMergeObjects(ArityType arity) { auto [_, tagField, valField] = getFromStack(1); // Move the incoming accumulator state from the stack. Given that we are now the owner of the // state we are free to do any in-place update as we see fit. @@ -2239,7 +2185,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinMergeObjects(Ar return {true, tagAgg, valAgg}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSet(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSet(ArityType arity) { auto [ownAgg, tagAgg, valAgg] = getFromStack(0); auto [tagField, valField] = moveOwnedFromStack(1); value::ValueGuard guardField{tagField, valField}; @@ -2265,7 +2211,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSet(ArityT return {ownAgg, tagAgg, valAgg}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::addToSetCappedImpl( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::addToSetCappedImpl( value::TypeTags tagNewElem, value::Value valNewElem, int32_t sizeCap, @@ -2331,7 +2277,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::addToSetCappedImpl( return {ownArr, tagArr, valArr}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSetCapped(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSetCapped(ArityType arity) { auto [tagNewElem, valNewElem] = moveOwnedFromStack(1); value::ValueGuard guardNewElem{tagNewElem, valNewElem}; auto [_, tagSizeCap, valSizeCap] = getFromStack(2); @@ -2347,7 +2293,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAddToSetCapped( tagNewElem, valNewElem, value::bitcastTo<int32_t>(valSizeCap), nullptr /*collator*/); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSet(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSet(ArityType arity) { auto [ownAgg, tagAgg, valAgg] = getFromStack(0); auto [ownColl, tagColl, valColl] = getFromStack(1); auto [tagField, valField] = moveOwnedFromStack(2); @@ -2381,7 +2327,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSet(Ar return {ownAgg, tagAgg, valAgg}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSetCapped( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSetCapped( ArityType arity) { auto [_1, tagColl, valColl] = getFromStack(1); auto [tagNewElem, valNewElem] = moveOwnedFromStack(2); @@ -2403,7 +2349,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollAddToSetCap value::getCollatorView(valColl)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRunJsPredicate(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRunJsPredicate(ArityType arity) { invariant(arity == 2); auto [predicateOwned, predicateType, predicateValue] = getFromStack(0); @@ -2429,7 +2375,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRunJsPredicate( return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(predicateResult)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinReplaceOne(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinReplaceOne(ArityType arity) { invariant(arity == 3); auto [ownedInputStr, typeTagInputStr, valueInputStr] = getFromStack(0); @@ -2469,7 +2415,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinReplaceOne(Arit return {true, outputStrTypeTag, outputStrValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum(ArityType arity) { invariant(arity >= 1); value::TypeTags resultTag = value::TypeTags::NumberInt32; @@ -2569,17 +2515,17 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDoubleDoubleSum */ using DateFn = std::function<Date_t( TimeZone, long long, long long, long long, long long, long long, long long, long long)>; -std::tuple<bool, value::TypeTags, value::Value> builtinDateHelper( +FastTuple<bool, value::TypeTags, value::Value> builtinDateHelper( DateFn computeDateFn, - std::tuple<bool, value::TypeTags, value::Value> tzdb, - std::tuple<bool, value::TypeTags, value::Value> yearOrWeekYear, - std::tuple<bool, value::TypeTags, value::Value> monthOrWeek, - std::tuple<bool, value::TypeTags, value::Value> day, - std::tuple<bool, value::TypeTags, value::Value> hour, - std::tuple<bool, value::TypeTags, value::Value> minute, - std::tuple<bool, value::TypeTags, value::Value> second, - std::tuple<bool, value::TypeTags, value::Value> millisecond, - std::tuple<bool, value::TypeTags, value::Value> timezone) { + FastTuple<bool, value::TypeTags, value::Value> tzdb, + FastTuple<bool, value::TypeTags, value::Value> yearOrWeekYear, + FastTuple<bool, value::TypeTags, value::Value> monthOrWeek, + FastTuple<bool, value::TypeTags, value::Value> day, + FastTuple<bool, value::TypeTags, value::Value> hour, + FastTuple<bool, value::TypeTags, value::Value> minute, + FastTuple<bool, value::TypeTags, value::Value> second, + FastTuple<bool, value::TypeTags, value::Value> millisecond, + FastTuple<bool, value::TypeTags, value::Value> timezone) { auto [ownedTzdb, typeTagTzdb, valueTzdb] = tzdb; auto [ownedYearOrWeekYear, typeTagYearOrWeekYear, valueYearOrWeekYear] = yearOrWeekYear; @@ -2617,7 +2563,7 @@ std::tuple<bool, value::TypeTags, value::Value> builtinDateHelper( return {false, value::TypeTags::Date, value::bitcastFrom<int64_t>(date.asInt64())}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDate(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDate(ArityType arity) { auto timeZoneDBTuple = getFromStack(0); auto yearTuple = getFromStack(1); auto monthTuple = getFromStack(2); @@ -2650,7 +2596,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDate(ArityType timezoneTuple); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateDiff(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateDiff(ArityType arity) { invariant(arity == 5 || arity == 6); // 6th parameter is 'startOfWeek'. auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(0); @@ -2710,7 +2656,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateDiff(ArityT return {false, value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(result)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateWeekYear(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateWeekYear(ArityType arity) { auto timeZoneDBTuple = getFromStack(0); auto yearTuple = getFromStack(1); auto weekTuple = getFromStack(2); @@ -2743,7 +2689,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateWeekYear(Ar timezoneTuple); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateToParts(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateToParts(ArityType arity) { auto [timezoneDBOwn, timezoneDBTag, timezoneDBVal] = getFromStack(0); if (timezoneDBTag != value::TypeTags::timeZoneDB) { return {false, value::TypeTags::Nothing, 0}; @@ -2782,7 +2728,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateToParts(Ari return {true, dateObjTag, dateObjVal}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsoDateToParts(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsoDateToParts(ArityType arity) { auto [timezoneDBOwn, timezoneDBTag, timezoneDBVal] = getFromStack(0); if (timezoneDBTag != value::TypeTags::timeZoneDB) { return {false, value::TypeTags::Nothing, 0}; @@ -2821,7 +2767,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsoDateToParts( return {true, dateObjTag, dateObjVal}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfYear(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfYear(ArityType arity) { invariant(arity == 3); auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(0); @@ -2831,7 +2777,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfYear(Arity timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfMonth(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfMonth(ArityType arity) { invariant(arity == 3); auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(0); @@ -2841,7 +2787,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfMonth(Arit timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfWeek(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfWeek(ArityType arity) { invariant(arity == 3); auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(0); @@ -2851,7 +2797,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDayOfWeek(Arity timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition(ArityType arity) { invariant(arity == 3); auto [ownedMask, maskTag, maskValue] = getFromStack(0); @@ -2913,7 +2859,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition bitTestBehavior == BitTestBehavior::AllClear)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestZero(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestZero(ArityType arity) { invariant(arity == 2); auto [maskOwned, maskTag, maskValue] = getFromStack(0); auto [inputOwned, inputTag, inputValue] = getFromStack(1); @@ -2929,7 +2875,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestZero(Ari return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestMask(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestMask(ArityType arity) { invariant(arity == 2); auto [maskOwned, maskTag, maskValue] = getFromStack(0); auto [inputOwned, inputTag, inputValue] = getFromStack(1); @@ -2945,7 +2891,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestMask(Ari return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(result)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBsonSize(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinBsonSize(ArityType arity) { auto [_, tagOperand, valOperand] = getFromStack(0); if (tagOperand == value::TypeTags::Object) { @@ -2961,7 +2907,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinBsonSize(ArityT return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinToUpper(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinToUpper(ArityType arity) { auto [_, operandTag, operandVal] = getFromStack(0); if (value::isString(operandTag)) { @@ -2974,7 +2920,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinToUpper(ArityTy return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinToLower(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinToLower(ArityType arity) { auto [_, operandTag, operandVal] = getFromStack(0); if (value::isString(operandTag)) { @@ -2987,7 +2933,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinToLower(ArityTy return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCoerceToString(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCoerceToString(ArityType arity) { auto [operandOwn, operandTag, operandVal] = getFromStack(0); if (value::isString(operandTag)) { @@ -3047,82 +2993,82 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCoerceToString( return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAcos(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAcos(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAcos(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAcosh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAcosh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAcosh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAsin(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAsin(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAsin(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAsinh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAsinh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAsinh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtan(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtan(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAtan(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtanh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtanh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericAtanh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtan2(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinAtan2(ArityType arity) { auto [owned1, operandTag1, operandValue1] = getFromStack(0); auto [owned2, operandTag2, operandValue2] = getFromStack(1); return genericAtan2(operandTag1, operandValue1, operandTag2, operandValue2); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCos(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCos(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericCos(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCosh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCosh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericCosh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDegreesToRadians(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDegreesToRadians(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericDegreesToRadians(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRadiansToDegrees(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRadiansToDegrees(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericRadiansToDegrees(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSin(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSin(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericSin(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSinh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSinh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericSinh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTan(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTan(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericTan(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTanh(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTanh(ArityType arity) { auto [_, operandTag, operandValue] = getFromStack(0); return genericTanh(operandTag, operandValue); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRound(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRound(ArityType arity) { invariant(arity == 1); auto [owned, tag, val] = getFromStack(0); @@ -3161,7 +3107,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRound(ArityType } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinConcat(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinConcat(ArityType arity) { StringBuilder result; for (ArityType idx = 0; idx < arity; ++idx) { auto [_, tag, value] = getFromStack(idx); @@ -3221,7 +3167,7 @@ std::pair<value::TypeTags, value::Value> ByteCode::genericIsMember(value::TypeTa return genericIsMember(lhsTag, lhsVal, rhsTag, rhsVal, collator); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsMember(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsMember(ArityType arity) { invariant(arity == 2); auto [ownedInput, inputTag, inputVal] = getFromStack(0); @@ -3231,7 +3177,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsMember(ArityT return {false, resultTag, resultVal}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollIsMember(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollIsMember(ArityType arity) { invariant(arity == 3); auto [ownedColl, collTag, collVal] = getFromStack(0); @@ -3244,7 +3190,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollIsMember(Ar return {false, resultTag, resultVal}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfBytes(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfBytes(ArityType arity) { auto [strOwn, strTag, strVal] = getFromStack(0); auto [substrOwn, substrTag, substrVal] = getFromStack(1); if ((!value::isString(strTag)) || (!value::isString(substrTag))) { @@ -3292,7 +3238,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfBytes(Ar return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(-1)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfCP(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfCP(ArityType arity) { auto [strOwn, strTag, strVal] = getFromStack(0); auto [substrOwn, substrTag, substrVal] = getFromStack(1); if ((!value::isString(strTag)) || (!value::isString(substrTag))) { @@ -3363,7 +3309,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIndexOfCP(Arity return {false, value::TypeTags::NumberInt32, value::bitcastFrom<int32_t>(-1)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimeUnit(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimeUnit(ArityType arity) { invariant(arity == 1); auto [timeUnitOwn, timeUnitTag, timeUnitValue] = getFromStack(0); if (!value::isString(timeUnitTag)) { @@ -3375,7 +3321,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimeUnit(Arit isValidTimeUnit(value::getStringView(timeUnitTag, timeUnitValue)))}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsDayOfWeek(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsDayOfWeek(ArityType arity) { invariant(arity == 1); auto [dayOfWeekOwn, dayOfWeekTag, dayOfWeekValue] = getFromStack(0); if (!value::isString(dayOfWeekTag)) { @@ -3387,7 +3333,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsDayOfWeek(Ari isValidDayOfWeek(value::getStringView(dayOfWeekTag, dayOfWeekValue)))}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimezone(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimezone(ArityType arity) { auto [timezoneDBOwn, timezoneDBTag, timezoneDBVal] = getFromStack(0); if (timezoneDBTag != value::TypeTags::timeZoneDB) { return {false, value::TypeTags::Nothing, 0}; @@ -3405,7 +3351,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsTimezone(Arit } namespace { -std::tuple<bool, value::TypeTags, value::Value> setUnion( +FastTuple<bool, value::TypeTags, value::Value> setUnion( const std::vector<value::TypeTags>& argTags, const std::vector<value::Value>& argVals, const CollatorInterface* collator = nullptr) { @@ -3429,7 +3375,7 @@ std::tuple<bool, value::TypeTags, value::Value> setUnion( return {true, resTag, resVal}; } -std::tuple<bool, value::TypeTags, value::Value> setIntersection( +FastTuple<bool, value::TypeTags, value::Value> setIntersection( const std::vector<value::TypeTags>& argTags, const std::vector<value::Value>& argVals, const CollatorInterface* collator = nullptr) { @@ -3492,7 +3438,7 @@ value::ValueSetType valueToSetHelper(const value::TypeTags& tag, return setValues; } -std::tuple<bool, value::TypeTags, value::Value> setDifference( +FastTuple<bool, value::TypeTags, value::Value> setDifference( value::TypeTags lhsTag, value::Value lhsVal, value::TypeTags rhsTag, @@ -3518,7 +3464,7 @@ std::tuple<bool, value::TypeTags, value::Value> setDifference( return {true, resTag, resVal}; } -std::tuple<bool, value::TypeTags, value::Value> setEquals( +FastTuple<bool, value::TypeTags, value::Value> setEquals( const std::vector<value::TypeTags>& argTags, const std::vector<value::Value>& argVals, const CollatorInterface* collator = nullptr) { @@ -3535,7 +3481,7 @@ std::tuple<bool, value::TypeTags, value::Value> setEquals( } } // namespace -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetUnion(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetUnion(ArityType arity) { invariant(arity >= 1); auto [_, collTag, collVal] = getFromStack(0); @@ -3558,7 +3504,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetUnion(Ar return setUnion(argTags, argVals, value::getCollatorView(collVal)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetUnion(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetUnion(ArityType arity) { std::vector<value::TypeTags> argTags; std::vector<value::Value> argVals; @@ -3575,7 +3521,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetUnion(ArityT return setUnion(argTags, argVals); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetIntersection( +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetIntersection( ArityType arity) { invariant(arity >= 1); @@ -3600,7 +3546,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetIntersec return setIntersection(argTags, argVals, value::getCollatorView(collVal)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetIntersection(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetIntersection(ArityType arity) { std::vector<value::TypeTags> argTags; std::vector<value::Value> argVals; @@ -3617,8 +3563,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetIntersection return setIntersection(argTags, argVals); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetDifference( - ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetDifference(ArityType arity) { invariant(arity == 3); auto [_, collTag, collVal] = getFromStack(0); @@ -3636,7 +3581,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetDifferen return setDifference(lhsTag, lhsVal, rhsTag, rhsVal, value::getCollatorView(collVal)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetEquals(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetEquals(ArityType arity) { invariant(arity >= 3); auto [_, collTag, collVal] = getFromStack(0); @@ -3660,7 +3605,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinCollSetEquals(A return setEquals(argTags, argVals, value::getCollatorView(collVal)); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetDifference(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetDifference(ArityType arity) { invariant(arity == 2); auto [lhsOwned, lhsTag, lhsVal] = getFromStack(0); @@ -3673,7 +3618,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetDifference(A return setDifference(lhsTag, lhsVal, rhsTag, rhsVal); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetEquals(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSetEquals(ArityType arity) { invariant(arity >= 2); std::vector<value::TypeTags> argTags; @@ -3703,11 +3648,11 @@ namespace { * - isMatch: Boolean flag to mark if the caller function is $regexMatch, in which case the result * returned is true/false. */ -std::tuple<bool, value::TypeTags, value::Value> pcreNextMatch(pcre::Regex* pcre, - StringData inputString, - uint32_t& startBytePos, - uint32_t& codePointPos, - bool isMatch) { +FastTuple<bool, value::TypeTags, value::Value> pcreNextMatch(pcre::Regex* pcre, + StringData inputString, + uint32_t& startBytePos, + uint32_t& codePointPos, + bool isMatch) { pcre::MatchData m = pcre->matchView(inputString, {}, startBytePos); if (!m && m.error() != pcre::Errc::ERROR_NOMATCH) { LOGV2_ERROR(5073414, @@ -3766,7 +3711,7 @@ std::tuple<bool, value::TypeTags, value::Value> pcreNextMatch(pcre::Regex* pcre, * A helper function with common logic for $regexMatch and $regexFind functions. Both extract only * the first match to a regular expression, but return different result objects. */ -std::tuple<bool, value::TypeTags, value::Value> genericPcreRegexSingleMatch( +FastTuple<bool, value::TypeTags, value::Value> genericPcreRegexSingleMatch( value::TypeTags typeTagPcreRegex, value::Value valuePcreRegex, value::TypeTags typeTagInputStr, @@ -3816,7 +3761,7 @@ std::pair<value::TypeTags, value::Value> collComparisonKey(value::TypeTags tag, } // namespace -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexCompile(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexCompile(ArityType arity) { invariant(arity == 2); auto [patternOwned, patternTypeTag, patternValue] = getFromStack(0); @@ -3837,7 +3782,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexCompile(Ar return {true, pcreTag, pcreValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexMatch(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexMatch(ArityType arity) { invariant(arity == 2); auto [ownedPcreRegex, tagPcreRegex, valPcreRegex] = getFromStack(0); auto [ownedInputStr, tagInputStr, valInputStr] = getFromStack(1); @@ -3863,7 +3808,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexMatch(Arit return genericPcreRegexSingleMatch(tagPcreRegex, valPcreRegex, tagInputStr, valInputStr, true); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFind(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFind(ArityType arity) { invariant(arity == 2); auto [ownedPcreRegex, typeTagPcreRegex, valuePcreRegex] = getFromStack(0); auto [ownedInputStr, typeTagInputStr, valueInputStr] = getFromStack(1); @@ -3872,7 +3817,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFind(Arity typeTagPcreRegex, valuePcreRegex, typeTagInputStr, valueInputStr, false); } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFindAll(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFindAll(ArityType arity) { invariant(arity == 2); auto [ownedPcre, typeTagPcreRegex, valuePcreRegex] = getFromStack(0); auto [ownedStr, typeTagInputStr, valueInputStr] = getFromStack(1); @@ -3931,7 +3876,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinRegexFindAll(Ar return {true, arrTag, arrVal}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardFilter(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardFilter(ArityType arity) { invariant(arity == 2); auto [ownedFilter, filterTag, filterValue] = getFromStack(0); @@ -3956,7 +3901,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardFilter(Ari value::getShardFiltererView(filterValue)->keyBelongsToMe(keyAsUnownedBson))}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardHash(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardHash(ArityType arity) { invariant(arity == 1); auto [ownedShardKey, shardKeyTag, shardKeyValue] = getFromStack(0); @@ -3971,7 +3916,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinShardHash(Arity return {false, value::TypeTags::NumberInt64, value::bitcastFrom<decltype(hashVal)>(hashVal)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinExtractSubArray(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinExtractSubArray(ArityType arity) { // We need to ensure that 'size_t' is wide enough to store 32-bit index. static_assert(sizeof(size_t) >= sizeof(int32_t), "size_t must be at least 32-bits"); @@ -4084,7 +4029,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinExtractSubArray return {true, resultTag, resultValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsArrayEmpty(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsArrayEmpty(ArityType arity) { invariant(arity == 1); auto [arrayOwned, arrayType, arrayValue] = getFromStack(0); @@ -4105,7 +4050,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinIsArrayEmpty(Ar } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinHasNullBytes(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinHasNullBytes(ArityType arity) { invariant(arity == 1); auto [strOwned, strType, strValue] = getFromStack(0); @@ -4119,7 +4064,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinHasNullBytes(Ar return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(hasNullBytes)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexPattern(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexPattern(ArityType arity) { invariant(arity == 1); auto [regexOwned, regexType, regexValue] = getFromStack(0); @@ -4133,7 +4078,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexPattern return {true, strType, strValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexFlags(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexFlags(ArityType arity) { invariant(arity == 1); auto [regexOwned, regexType, regexValue] = getFromStack(0); @@ -4147,7 +4092,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGetRegexFlags(A return {true, strType, strValue}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGenerateSortKey(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinGenerateSortKey(ArityType arity) { invariant(arity == 2 || arity == 3); auto [ssOwned, ssTag, ssVal] = getFromStack(0); @@ -4185,7 +4130,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinGenerateSortKey new KeyString::Value(ss->generateSortKey(obj, collator)))}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinMakeBsonObj(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinMakeBsonObj(ArityType arity) { invariant(arity >= 2); tassert(6897002, str::stream() << "Unsupported number of arguments passed to makeBsonObj(): " << arity, @@ -4211,7 +4156,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinMakeBsonObj(Ari return {true, tag, val}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinReverseArray(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinReverseArray(ArityType arity) { invariant(arity == 1); auto [inputOwned, inputType, inputVal] = getFromStack(0); @@ -4275,7 +4220,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinReverseArray(Ar } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSortArray(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSortArray(ArityType arity) { invariant(arity == 2 || arity == 3); auto [inputOwned, inputType, inputVal] = getFromStack(0); @@ -4366,7 +4311,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinSortArray(Arity } } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateAdd(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateAdd(ArityType arity) { invariant(arity == 5); auto [timezoneDBOwn, timezoneDBTag, timezoneDBVal] = getFromStack(0); @@ -4408,7 +4353,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinDateAdd(ArityTy false, value::TypeTags::Date, value::bitcastFrom<int64_t>(resDate.toMillisSinceEpoch())}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinFtsMatch(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinFtsMatch(ArityType arity) { invariant(arity == 2); auto [matcherOwn, matcherTag, matcherVal] = getFromStack(0); @@ -4433,7 +4378,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinFtsMatch(ArityT return {false, value::TypeTags::Boolean, value::bitcastFrom<bool>(matches)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsSecond(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsSecond(ArityType arity) { invariant(arity == 1); auto [inputValueOwn, inputTypeTag, inputValue] = getFromStack(0); @@ -4446,7 +4391,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsSecond(ArityT return {false, value::TypeTags::NumberInt64, value::bitcastFrom<uint64_t>(timestamp.getSecs())}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsIncrement(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsIncrement(ArityType arity) { invariant(arity == 1); auto [inputValueOwn, inputTypeTag, inputValue] = getFromStack(0); @@ -4459,7 +4404,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTsIncrement(Ari return {false, value::TypeTags::NumberInt64, value::bitcastFrom<uint64_t>(timestamp.getInc())}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinHash(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinHash(ArityType arity) { auto hashVal = value::hashInit(); for (ArityType idx = 0; idx < arity; ++idx) { auto [owned, tag, val] = getFromStack(idx); @@ -4469,7 +4414,7 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinHash(ArityType return {false, value::TypeTags::NumberInt64, value::bitcastFrom<decltype(hashVal)>(hashVal)}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTypeMatch(ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinTypeMatch(ArityType arity) { invariant(arity == 2); auto [inputOwn, inputTag, inputVal] = getFromStack(0); @@ -4484,8 +4429,8 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::builtinTypeMatch(Arity return {false, value::TypeTags::Nothing, 0}; } -std::tuple<bool, value::TypeTags, value::Value> ByteCode::dispatchBuiltin(Builtin f, - ArityType arity) { +FastTuple<bool, value::TypeTags, value::Value> ByteCode::dispatchBuiltin(Builtin f, + ArityType arity) { switch (f) { case Builtin::dateDiff: return builtinDateDiff(arity); @@ -4697,20 +4642,16 @@ std::tuple<bool, value::TypeTags, value::Value> ByteCode::dispatchBuiltin(Builti MONGO_COMPILER_NORETURN void reportSwapFailure(); void ByteCode::swapStack() { - auto backOffset = _argStack.size() - 1; - auto& rhsOwnedTag = _argStack.ownedAndTag(backOffset); - auto& rhsValue = _argStack.value(backOffset); - --backOffset; - auto& lhsOwnedTag = _argStack.ownedAndTag(backOffset); - auto& lhsValue = _argStack.value(backOffset); - - if (rhsValue == lhsValue && rhsOwnedTag.tag == lhsOwnedTag.tag) { - if (rhsOwnedTag.owned && !isShallowType(rhsOwnedTag.tag)) { + auto [rhsOwned, rhsTag, rhsValue] = getFromStack(0); + auto [lhsOwned, lhsTag, lhsValue] = getFromStack(1); + + if (rhsValue == lhsValue && rhsTag == lhsTag) { + if (rhsOwned && !isShallowType(rhsTag)) { reportSwapFailure(); } } else { - std::swap(rhsOwnedTag, lhsOwnedTag); - std::swap(rhsValue, lhsValue); + setStack(0, lhsOwned, lhsTag, lhsValue); + setStack(1, rhsOwned, rhsTag, rhsValue); } } @@ -4718,6 +4659,57 @@ MONGO_COMPILER_NORETURN void reportSwapFailure() { tasserted(56123, "Attempting to swap two identical values when top of stack is owned"); } +MONGO_COMPILER_NORETURN void ByteCode::runFailInstruction() { + auto [ownedCode, tagCode, valCode] = getFromStack(1); + invariant(tagCode == value::TypeTags::NumberInt64); + + auto [ownedMsg, tagMsg, valMsg] = getFromStack(0); + invariant(value::isString(tagMsg)); + + ErrorCodes::Error code{static_cast<ErrorCodes::Error>(value::bitcastTo<int64_t>(valCode))}; + std::string message{value::getStringView(tagMsg, valMsg)}; + + uasserted(code, message); +} + +void ByteCode::runClassicMatcher(const MatchExpression* matcher) { + auto [ownedObj, tagObj, valObj] = getFromStack(0); + + BSONObj bsonObjForMatching; + if (tagObj == value::TypeTags::Object) { + BSONObjBuilder builder; + sbe::bson::convertToBsonObj(builder, sbe::value::getObjectView(valObj)); + bsonObjForMatching = builder.obj(); + } else if (tagObj == value::TypeTags::bsonObject) { + auto bson = value::getRawPointerView(valObj); + bsonObjForMatching = BSONObj(bson); + } else { + MONGO_UNREACHABLE_TASSERT(6681402); + } + + bool res = matcher->matchesBSON(bsonObjForMatching); + if (ownedObj) { + value::releaseValue(tagObj, valObj); + } + topStack(false, value::TypeTags::Boolean, value::bitcastFrom<bool>(res)); +} +template <typename T> +void ByteCode::runTagCheck(T&& predicate) { + auto [owned, tag, val] = getFromStack(0); + + if (tag != value::TypeTags::Nothing) { + topStack(false, value::TypeTags::Boolean, value::bitcastFrom<bool>(predicate(tag))); + } + + if (owned) { + value::releaseValue(tag, val); + } +} + +void ByteCode::runTagCheck(value::TypeTags tagRhs) { + runTagCheck([tagRhs](value::TypeTags tagLhs) { return tagLhs == tagRhs; }); +} + void ByteCode::runLambdaInternal(const CodeFragment* code, int64_t position) { runInternal(code, position); swapStack(); @@ -5599,101 +5591,31 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) { break; } case Instruction::isNull: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(tag == value::TypeTags::Null)); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::TypeTags::Null); break; } case Instruction::isObject: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isObject(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isObject); break; } case Instruction::isArray: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isArray(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isArray); break; } case Instruction::isString: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isString(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isString); break; } case Instruction::isNumber: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isNumber(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isNumber); break; } case Instruction::isBinData: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isBinData(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isBinData); break; } case Instruction::isDate: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(tag == value::TypeTags::Date)); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::TypeTags::Date); break; } case Instruction::isNaN: { @@ -5723,59 +5645,19 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) { break; } case Instruction::isRecordId: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(value::isRecordId(tag))); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::isRecordId); break; } case Instruction::isMinKey: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(tag == value::TypeTags::MinKey)); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::TypeTags::MinKey); break; } case Instruction::isMaxKey: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(tag == value::TypeTags::MaxKey)); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::TypeTags::MaxKey); break; } case Instruction::isTimestamp: { - auto [owned, tag, val] = getFromStack(0); - - if (tag != value::TypeTags::Nothing) { - topStack(false, - value::TypeTags::Boolean, - value::bitcastFrom<bool>(tag == value::TypeTags::Timestamp)); - } - - if (owned) { - value::releaseValue(tag, val); - } + runTagCheck(value::TypeTags::Timestamp); break; } case Instruction::function: @@ -5839,43 +5721,14 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) { break; } case Instruction::fail: { - auto [ownedCode, tagCode, valCode] = getFromStack(1); - invariant(tagCode == value::TypeTags::NumberInt64); - - auto [ownedMsg, tagMsg, valMsg] = getFromStack(0); - invariant(value::isString(tagMsg)); - - ErrorCodes::Error code{ - static_cast<ErrorCodes::Error>(value::bitcastTo<int64_t>(valCode))}; - std::string message{value::getStringView(tagMsg, valMsg)}; - - uasserted(code, message); - + runFailInstruction(); break; } case Instruction::applyClassicMatcher: { const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer); pcPointer += sizeof(matcher); - auto [ownedObj, tagObj, valObj] = getFromStack(0); - - BSONObj bsonObjForMatching; - if (tagObj == value::TypeTags::Object) { - BSONObjBuilder builder; - sbe::bson::convertToBsonObj(builder, sbe::value::getObjectView(valObj)); - bsonObjForMatching = builder.obj(); - } else if (tagObj == value::TypeTags::bsonObject) { - auto bson = value::getRawPointerView(valObj); - bsonObjForMatching = BSONObj(bson); - } else { - MONGO_UNREACHABLE_TASSERT(6681402); - } - - bool res = matcher->matchesBSON(bsonObjForMatching); - if (ownedObj) { - value::releaseValue(tagObj, valObj); - } - topStack(false, value::TypeTags::Boolean, value::bitcastFrom<bool>(res)); + runClassicMatcher(matcher); break; } default: @@ -5885,32 +5738,29 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) { } } -std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragment* code) { - uassert(6040900, "The evaluation stack must be empty", _argStack.size() == 0); - - ON_BLOCK_EXIT([&] { - auto size = _argStack.size(); - for (size_t i = 0; i < size; ++i) { - auto [owned, tag] = _argStack.ownedAndTag(i); - if (owned) { - value::releaseValue(tag, _argStack.value(i)); - } - } - - _argStack.resize(0); - }); - - runInternal(code, 0); +FastTuple<bool, value::TypeTags, value::Value> ByteCode::run(const CodeFragment* code) { + try { + uassert(6040900, + "The evaluation stack must be empty", + _argStackTop + sizeOfElement == _argStack); - uassert(4822801, "The evaluation stack must hold only a single value", _argStack.size() == 1); + runInternal(code, 0); - auto [owned, tag] = _argStack.ownedAndTag(0); - auto val = _argStack.value(0); + uassert(4822801, + "The evaluation stack must hold only a single value", + _argStackTop == _argStack); - // Transfer ownership of tag/val to the caller - _argStack.resize(0); + // Transfer ownership of tag/val to the caller + stackReset(); - return {owned, tag, val}; + return readTuple(_argStack); + } catch (...) { + auto sentinel = _argStack - sizeOfElement; + while (_argStackTop != sentinel) { + popAndReleaseStack(); + } + throw; + } } bool ByteCode::runPredicate(const CodeFragment* code) { |