summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec
diff options
context:
space:
mode:
authorIan Boros <ian.boros@mongodb.com>2022-05-26 20:45:45 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-06-07 22:42:07 +0000
commit6385b8fe69e121ab2bf50297fdeab5e4f2729d5a (patch)
treec4989057c5cb94fb87a3417253b6b68f3c33b8c6 /src/mongo/db/exec
parentbe3cfbd6d6c195f0179066b111a39291f0f15df7 (diff)
downloadmongo-6385b8fe69e121ab2bf50297fdeab5e4f2729d5a.tar.gz
SERVER-66814 Use classic MatchExpression for applying filters in SBE
Co-authored-by: Eric Cox <eric.cox@mongodb.com>
Diffstat (limited to 'src/mongo/db/exec')
-rw-r--r--src/mongo/db/exec/sbe/expressions/expression.cpp17
-rw-r--r--src/mongo/db/exec/sbe/values/value.cpp3
-rw-r--r--src/mongo/db/exec/sbe/values/value.h13
-rw-r--r--src/mongo/db/exec/sbe/values/value_printer.cpp6
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.cpp44
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.h5
6 files changed, 88 insertions, 0 deletions
diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp
index 61812667316..970543b706a 100644
--- a/src/mongo/db/exec/sbe/expressions/expression.cpp
+++ b/src/mongo/db/exec/sbe/expressions/expression.cpp
@@ -582,6 +582,11 @@ static stdx::unordered_map<std::string, InstrFn> kInstrFunctions = {
{"collMin", InstrFn{[](size_t n) { return n == 2; }, &vm::CodeFragment::appendCollMin, true}},
{"collMax", InstrFn{[](size_t n) { return n == 2; }, &vm::CodeFragment::appendCollMax, true}},
{"mod", InstrFn{[](size_t n) { return n == 2; }, &vm::CodeFragment::appendMod, false}},
+ // Note that we do not provide a pointer to a function for appending the 'applyClassicMatcher'
+ // instruction, because it's required that the first argument to applyClassicMatcher be a
+ // constant MatchExpression. This constant is stored as part of the bytecode itself, to avoid
+ // the stack manipulation overhead.
+ {"applyClassicMatcher", InstrFn{[](size_t n) { return n == 2; }, nullptr, false}},
};
} // namespace
@@ -689,6 +694,18 @@ vm::CodeFragment EFunction::compileDirect(CompileCtx& ctx) const {
code.appendTraverseP(bodyPosition);
return code;
+ } else if (_name == "applyClassicMatcher") {
+ tassert(6681400,
+ "First argument to applyClassicMatcher must be constant",
+ _nodes[0]->as<EConstant>());
+ auto [matcherTag, matcherVal] = _nodes[0]->as<EConstant>()->getConstant();
+ tassert(6681409,
+ "First argument to applyClassicMatcher must be a classic matcher",
+ matcherTag == value::TypeTags::classicMatchExpresion);
+
+ code.append(_nodes[1]->compileDirect(ctx));
+ code.appendApplyClassicMatcher(value::getClassicMatchExpressionView(matcherVal));
+ return code;
}
// The order of evaluation is flipped for instruction functions. We may want to change the
diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp
index cde56e31ba2..5bbdc40170e 100644
--- a/src/mongo/db/exec/sbe/values/value.cpp
+++ b/src/mongo/db/exec/sbe/values/value.cpp
@@ -326,6 +326,9 @@ void releaseValue(TypeTags tag, Value val) noexcept {
case TypeTags::indexBounds:
delete getIndexBoundsView(val);
break;
+ case TypeTags::classicMatchExpresion:
+ delete getClassicMatchExpressionView(val);
+ break;
default:
break;
}
diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h
index 728a0c16634..d0202b0f1c0 100644
--- a/src/mongo/db/exec/sbe/values/value.h
+++ b/src/mongo/db/exec/sbe/values/value.h
@@ -154,6 +154,9 @@ enum class TypeTags : uint8_t {
// Pointer to a IndexBounds object.
indexBounds,
+
+ // Pointer to a classic engine match expression.
+ classicMatchExpresion,
};
inline constexpr bool isNumber(TypeTags tag) noexcept {
@@ -1249,6 +1252,10 @@ inline IndexBounds* getIndexBoundsView(Value val) noexcept {
return reinterpret_cast<IndexBounds*>(val);
}
+inline MatchExpression* getClassicMatchExpressionView(Value val) noexcept {
+ return reinterpret_cast<MatchExpression*>(val);
+}
+
/**
* Pattern and flags of Regex are stored in BSON as two C strings written one after another.
*
@@ -1450,6 +1457,12 @@ inline std::pair<TypeTags, Value> copyValue(TypeTags tag, Value val) {
return makeCopyCollator(*getCollatorView(val));
case TypeTags::indexBounds:
return makeCopyIndexBounds(*getIndexBoundsView(val));
+ case TypeTags::classicMatchExpresion:
+ // Beware: "shallow cloning" a match expression does not copy the underlying BSON. The
+ // original BSON must remain alive for both the original MatchExpression and the clone.
+ return {TypeTags::classicMatchExpresion,
+ bitcastFrom<const MatchExpression*>(
+ getClassicMatchExpressionView(val)->shallowClone().release())};
default:
break;
}
diff --git a/src/mongo/db/exec/sbe/values/value_printer.cpp b/src/mongo/db/exec/sbe/values/value_printer.cpp
index 78e655114a3..90a43442329 100644
--- a/src/mongo/db/exec/sbe/values/value_printer.cpp
+++ b/src/mongo/db/exec/sbe/values/value_printer.cpp
@@ -156,6 +156,9 @@ void ValuePrinter<T>::writeTagToStream(TypeTags tag) {
case TypeTags::indexBounds:
stream << "indexBounds";
break;
+ case TypeTags::classicMatchExpresion:
+ stream << "classicMatchExpression";
+ break;
default:
stream << "unknown tag";
break;
@@ -472,6 +475,9 @@ void ValuePrinter<T>::writeValueToStream(TypeTags tag, Value val, size_t depth)
getIndexBoundsView(val)->toString(true /* hasNonSimpleCollation */));
stream << ")";
break;
+ case TypeTags::classicMatchExpresion:
+ stream << "ClassicMatcher(" << getClassicMatchExpressionView(val)->toString() << ")";
+ break;
default:
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp
index f6a6b35970e..3aae133219f 100644
--- a/src/mongo/db/exec/sbe/vm/vm.cpp
+++ b/src/mongo/db/exec/sbe/vm/vm.cpp
@@ -153,6 +153,8 @@ int Instruction::stackOffset[Instruction::Tags::lastInstruction] = {
0, // ret
-1, // fail
+
+ 0, // applyClassicMatcher
};
namespace {
@@ -281,6 +283,12 @@ std::string CodeFragment::toString() const {
ss << "accessor: " << static_cast<void*>(accessor);
break;
}
+ case Instruction::applyClassicMatcher: {
+ const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer);
+ pcPointer += sizeof(matcher);
+ ss << "matcher: " << static_cast<const void*>(matcher);
+ break;
+ }
case Instruction::numConvert: {
auto tag = readFromMemory<value::TypeTags>(pcPointer);
pcPointer += sizeof(tag);
@@ -446,6 +454,17 @@ void CodeFragment::appendNumericConvert(value::TypeTags targetTag) {
offset += writeToMemory(offset, targetTag);
}
+void CodeFragment::appendApplyClassicMatcher(const MatchExpression* matcher) {
+ Instruction i;
+ i.tag = Instruction::applyClassicMatcher;
+ adjustStackSimple(i);
+
+ auto offset = allocateSpace(sizeof(Instruction) + sizeof(matcher));
+
+ offset += writeToMemory(offset, i);
+ offset += writeToMemory(offset, matcher);
+}
+
void CodeFragment::appendSub() {
appendSimpleInstruction(Instruction::sub);
}
@@ -5848,6 +5867,31 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) {
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));
+ break;
+ }
default:
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h
index 56d708fe1a1..801a139e5b8 100644
--- a/src/mongo/db/exec/sbe/vm/vm.h
+++ b/src/mongo/db/exec/sbe/vm/vm.h
@@ -321,6 +321,8 @@ struct Instruction {
fail,
+ applyClassicMatcher, // Instruction which calls into the classic engine MatchExpression.
+
lastInstruction // this is just a marker used to calculate number of instructions
};
@@ -481,6 +483,8 @@ struct Instruction {
return "ret";
case fail:
return "fail";
+ case applyClassicMatcher:
+ return "applyClassicMatcher";
default:
return "unrecognized";
}
@@ -769,6 +773,7 @@ public:
appendSimpleInstruction(Instruction::fail);
}
void appendNumericConvert(value::TypeTags targetTag);
+ void appendApplyClassicMatcher(const MatchExpression*);
void fixup(int offset);