summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/sbe/vm/vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/sbe/vm/vm.cpp')
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.cpp672
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) {