summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2023-02-03 23:42:29 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-02-04 01:32:37 +0000
commit94098eff431d7bb65da31516cc4df2a895d27dd8 (patch)
tree1aa862702400ebbf57026aa94e766b8d88b9e143 /src/mongo/db/exec
parent946646ef8d624116985f3acca5ec5ae359d59097 (diff)
downloadmongo-94098eff431d7bb65da31516cc4df2a895d27dd8.tar.gz
Revert "SERVER-71798 Expand the set of queries eligible for SBE in the 6.3 release"
Diffstat (limited to 'src/mongo/db/exec')
-rw-r--r--src/mongo/db/exec/plan_cache_util.cpp3
-rw-r--r--src/mongo/db/exec/plan_cache_util.h54
-rw-r--r--src/mongo/db/exec/sbe/expressions/expression.cpp16
-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.cpp42
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.h6
-rw-r--r--src/mongo/db/exec/sbe/vm/vm_printer.cpp36
9 files changed, 153 insertions, 26 deletions
diff --git a/src/mongo/db/exec/plan_cache_util.cpp b/src/mongo/db/exec/plan_cache_util.cpp
index f223afc79f9..265eb1e70e7 100644
--- a/src/mongo/db/exec/plan_cache_util.cpp
+++ b/src/mongo/db/exec/plan_cache_util.cpp
@@ -76,7 +76,8 @@ void updatePlanCache(OperationContext* opCtx,
const stage_builder::PlanStageData& data) {
// TODO SERVER-67576: re-enable caching of "explode for sort" plans in the SBE cache.
if (shouldCacheQuery(query) && collections.getMainCollection() &&
- !solution.hasExplodedForSort) {
+ !solution.hasExplodedForSort &&
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto key = plan_cache_key_factory::make(query, collections);
auto plan = std::make_unique<sbe::CachedSbePlan>(root.clone(), data);
plan->indexFilterApplied = solution.indexFilterApplied;
diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h
index 05b8e3d6a36..b233338882f 100644
--- a/src/mongo/db/exec/plan_cache_util.h
+++ b/src/mongo/db/exec/plan_cache_util.h
@@ -200,31 +200,35 @@ void updatePlanCache(
if (winningPlan.solution->cacheData != nullptr) {
if constexpr (std::is_same_v<PlanStageType, std::unique_ptr<sbe::PlanStage>>) {
- tassert(6142201,
- "The winning CandidatePlan should contain the original plan",
- winningPlan.clonedPlan);
-
- // Clone the winning SBE plan and its auxiliary data.
- auto cachedPlan =
- std::make_unique<sbe::CachedSbePlan>(std::move(winningPlan.clonedPlan->first),
- std::move(winningPlan.clonedPlan->second));
- cachedPlan->indexFilterApplied = winningPlan.solution->indexFilterApplied;
-
- auto buildDebugInfoFn =
- [soln = winningPlan.solution.get()]() -> plan_cache_debug_info::DebugInfoSBE {
- return buildDebugInfo(soln);
- };
- PlanCacheCallbacksImpl<sbe::PlanCacheKey,
- sbe::CachedSbePlan,
- plan_cache_debug_info::DebugInfoSBE>
- callbacks{query, buildDebugInfoFn};
- uassertStatusOK(sbe::getPlanCache(opCtx).set(
- plan_cache_key_factory::make(query, collections),
- std::move(cachedPlan),
- *rankingDecision,
- opCtx->getServiceContext()->getPreciseClockSource()->now(),
- &callbacks,
- boost::none /* worksGrowthCoefficient */));
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
+ tassert(6142201,
+ "The winning CandidatePlan should contain the original plan",
+ winningPlan.clonedPlan);
+ // Clone the winning SBE plan and its auxiliary data.
+ auto cachedPlan = std::make_unique<sbe::CachedSbePlan>(
+ std::move(winningPlan.clonedPlan->first),
+ std::move(winningPlan.clonedPlan->second));
+ cachedPlan->indexFilterApplied = winningPlan.solution->indexFilterApplied;
+
+ auto buildDebugInfoFn = [soln = winningPlan.solution.get()]()
+ -> plan_cache_debug_info::DebugInfoSBE { return buildDebugInfo(soln); };
+ PlanCacheCallbacksImpl<sbe::PlanCacheKey,
+ sbe::CachedSbePlan,
+ plan_cache_debug_info::DebugInfoSBE>
+ callbacks{query, buildDebugInfoFn};
+ uassertStatusOK(sbe::getPlanCache(opCtx).set(
+ plan_cache_key_factory::make(query, collections),
+ std::move(cachedPlan),
+ *rankingDecision,
+ opCtx->getServiceContext()->getPreciseClockSource()->now(),
+ &callbacks,
+ boost::none /* worksGrowthCoefficient */));
+ } else {
+ // Fall back to use the classic plan cache.
+ //
+ // TODO SERVER-64882: Remove this branch after "gFeatureFlagSbeFull" is removed.
+ cacheClassicPlan();
+ }
} else {
static_assert(std::is_same_v<PlanStageType, PlanStage*>);
cacheClassicPlan();
diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp
index 26266070fa2..a96a559cd2d 100644
--- a/src/mongo/db/exec/sbe/expressions/expression.cpp
+++ b/src/mongo/db/exec/sbe/expressions/expression.cpp
@@ -933,6 +933,21 @@ vm::CodeFragment generateTraverseCellTypes(CompileCtx& ctx,
return generatorLegacy<&vm::CodeFragment::appendTraverseCellTypes>(ctx, nodes, false);
}
+vm::CodeFragment generateClassicMatcher(CompileCtx& ctx, const EExpression::Vector& nodes, bool) {
+ 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);
+
+ vm::CodeFragment code;
+ code.append(nodes[1]->compileDirect(ctx));
+ code.appendApplyClassicMatcher(value::getClassicMatchExpressionView(matcherVal));
+ return code;
+}
+
/**
* The map of functions that resolve directly to instructions.
*/
@@ -971,6 +986,7 @@ static stdx::unordered_map<std::string, InstrFn> kInstrFunctions = {
{"isMinKey", InstrFn{1, generator<1, &vm::CodeFragment::appendIsMinKey>, false}},
{"isMaxKey", InstrFn{1, generator<1, &vm::CodeFragment::appendIsMaxKey>, false}},
{"isTimestamp", InstrFn{1, generator<1, &vm::CodeFragment::appendIsTimestamp>, false}},
+ {"applyClassicMatcher", InstrFn{2, generateClassicMatcher, false}},
};
} // namespace
diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp
index a24883a7be9..e21bc694784 100644
--- a/src/mongo/db/exec/sbe/values/value.cpp
+++ b/src/mongo/db/exec/sbe/values/value.cpp
@@ -348,6 +348,9 @@ void releaseValueDeep(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 88cf3d3b011..0459118ddf1 100644
--- a/src/mongo/db/exec/sbe/values/value.h
+++ b/src/mongo/db/exec/sbe/values/value.h
@@ -191,6 +191,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 {
@@ -1258,6 +1261,10 @@ inline IndexBounds* getIndexBoundsView(Value val) noexcept {
return reinterpret_cast<IndexBounds*>(val);
}
+inline MatchExpression* getClassicMatchExpressionView(Value val) noexcept {
+ return reinterpret_cast<MatchExpression*>(val);
+}
+
inline sbe::value::CsiCell* getCsiCellView(Value val) noexcept {
return reinterpret_cast<sbe::value::CsiCell*>(val);
}
@@ -1472,6 +1479,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 2405f698f3f..4cd70a9196b 100644
--- a/src/mongo/db/exec/sbe/values/value_printer.cpp
+++ b/src/mongo/db/exec/sbe/values/value_printer.cpp
@@ -163,6 +163,9 @@ void ValuePrinter<T>::writeTagToStream(TypeTags tag) {
case TypeTags::indexBounds:
stream << "indexBounds";
break;
+ case TypeTags::classicMatchExpresion:
+ stream << "classicMatchExpression";
+ break;
case TypeTags::csiCell:
stream << "csiCell";
break;
@@ -536,6 +539,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;
case TypeTags::csiCell:
stream << "CsiCell(" << getCsiCellView(val) << ")";
break;
diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp
index 35dab757964..3a8e48daf0a 100644
--- a/src/mongo/db/exec/sbe/vm/vm.cpp
+++ b/src/mongo/db/exec/sbe/vm/vm.cpp
@@ -166,6 +166,7 @@ int Instruction::stackOffset[Instruction::Tags::lastInstruction] = {
-1, // fail
+ 0, // applyClassicMatcher
0, // dateTruncImm
};
@@ -481,6 +482,18 @@ void CodeFragment::appendNumericConvert(value::TypeTags targetTag) {
adjustStackSimple(i);
}
+void CodeFragment::appendApplyClassicMatcher(const MatchExpression* matcher) {
+ Instruction i;
+ i.tag = Instruction::applyClassicMatcher;
+
+ auto offset = allocateSpace(sizeof(Instruction) + sizeof(matcher));
+
+ offset += writeToMemory(offset, i);
+ offset += writeToMemory(offset, matcher);
+
+ adjustStackSimple(i);
+}
+
void CodeFragment::appendSub(Instruction::Parameter lhs, Instruction::Parameter rhs) {
appendSimpleInstruction(Instruction::sub, lhs, rhs);
}
@@ -5737,6 +5750,28 @@ MONGO_COMPILER_NORETURN void ByteCode::runFailInstruction() {
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(const uint8_t*& pcPointer, T&& predicate) {
auto [popParam, offsetParam] = decodeParam(pcPointer);
@@ -6747,6 +6782,13 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) {
runFailInstruction();
break;
}
+ case Instruction::applyClassicMatcher: {
+ const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer);
+ pcPointer += sizeof(matcher);
+
+ runClassicMatcher(matcher);
+ break;
+ }
case Instruction::dateTruncImm: {
auto unit = readFromMemory<TimeUnit>(pcPointer);
pcPointer += sizeof(unit);
diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h
index 7034e1fabfe..b6ee6d2dc75 100644
--- a/src/mongo/db/exec/sbe/vm/vm.h
+++ b/src/mongo/db/exec/sbe/vm/vm.h
@@ -349,6 +349,8 @@ struct Instruction {
fail,
+ applyClassicMatcher, // Instruction which calls into the classic engine MatchExpression.
+
dateTruncImm,
lastInstruction // this is just a marker used to calculate number of instructions
@@ -575,6 +577,8 @@ struct Instruction {
return "allocStack";
case fail:
return "fail";
+ case applyClassicMatcher:
+ return "applyClassicMatcher";
case dateTruncImm:
return "dateTruncImm";
default:
@@ -886,6 +890,7 @@ public:
void appendAllocStack(uint32_t size);
void appendFail();
void appendNumericConvert(value::TypeTags targetTag);
+ void appendApplyClassicMatcher(const MatchExpression*);
// For printing from an interactive debugger.
std::string toString() const;
@@ -994,6 +999,7 @@ private:
void runLambdaInternal(const CodeFragment* code, int64_t position);
MONGO_COMPILER_NORETURN void runFailInstruction();
+ void runClassicMatcher(const MatchExpression* matcher);
template <typename T>
void runTagCheck(const uint8_t*& pcPointer, T&& predicate);
diff --git a/src/mongo/db/exec/sbe/vm/vm_printer.cpp b/src/mongo/db/exec/sbe/vm/vm_printer.cpp
index 85c59dc9957..8ac6fe532c2 100644
--- a/src/mongo/db/exec/sbe/vm/vm_printer.cpp
+++ b/src/mongo/db/exec/sbe/vm/vm_printer.cpp
@@ -49,6 +49,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug> {
return SlotAccessorFmt{accessor};
}
+ auto matchExpression(const MatchExpression* matcher) {
+ return MatchExpressionFmt{matcher};
+ }
+
struct PcPointerFmt {
const uint8_t* pcPointer;
};
@@ -56,6 +60,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug> {
struct SlotAccessorFmt {
value::SlotAccessor* accessor;
};
+
+ struct MatchExpressionFmt {
+ const MatchExpression* matcher;
+ };
};
template <typename charT, typename traits>
@@ -72,6 +80,13 @@ std::basic_ostream<charT, traits>& operator<<(
return os << static_cast<const void*>(a.accessor);
}
+template <typename charT, typename traits>
+std::basic_ostream<charT, traits>& operator<<(
+ std::basic_ostream<charT, traits>& os,
+ const CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug>::MatchExpressionFmt& a) {
+ return os << static_cast<const void*>(a.matcher);
+}
+
template <>
struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> {
CodeFragmentFormatter(const CodeFragment& code) : code(code) {}
@@ -84,6 +99,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> {
return SlotAccessorFmt{accessor};
}
+ auto matchExpression(const MatchExpression* matcher) {
+ return MatchExpressionFmt{matcher};
+ }
+
struct PcPointerFmt {
const uint8_t* pcPointer;
const uint8_t* pcBegin;
@@ -93,6 +112,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> {
value::SlotAccessor* accessor;
};
+ struct MatchExpressionFmt {
+ const MatchExpression* matcher;
+ };
+
const CodeFragment& code;
};
@@ -114,6 +137,13 @@ std::basic_ostream<charT, traits>& operator<<(
return os << "<accessor>";
}
+template <typename charT, typename traits>
+std::basic_ostream<charT, traits>& operator<<(
+ std::basic_ostream<charT, traits>& os,
+ const CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable>::MatchExpressionFmt& a) {
+ return os << "<matchExpression>";
+}
+
template <typename Formatter>
class CodeFragmentPrinterImpl {
public:
@@ -298,6 +328,12 @@ public:
os << "accessor: " << _formatter.slotAccessor(accessor);
break;
}
+ case Instruction::applyClassicMatcher: {
+ const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer);
+ pcPointer += sizeof(matcher);
+ os << "matcher: " << _formatter.matchExpression(matcher);
+ break;
+ }
case Instruction::numConvert: {
auto tag = readFromMemory<value::TypeTags>(pcPointer);
pcPointer += sizeof(tag);