SkSL interpreter now properly short-circuits boolean operators
Bug: skia:
Change-Id: If7acf4107498cabc049ad130814a3814383bd14b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243418
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 6977ea4..bb8caf1 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -627,6 +627,38 @@
}
}
}
+ int count = std::max(SlotCount(lType), SlotCount(rType));
+ switch (op) {
+ case Token::Kind::LOGICALAND: {
+ SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
+ this->write(ByteCodeInstruction::kDup);
+ this->write8(1);
+ this->write(ByteCodeInstruction::kMaskPush);
+ this->write(ByteCodeInstruction::kBranchIfAllFalse);
+ DeferredLocation falseLocation(this);
+ this->writeExpression(*b.fRight);
+ this->write(ByteCodeInstruction::kAndB);
+ falseLocation.set();
+ this->write(ByteCodeInstruction::kMaskPop);
+ return false;
+ }
+ case Token::Kind::LOGICALOR: {
+ SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
+ this->write(ByteCodeInstruction::kDup);
+ this->write8(1);
+ this->write(ByteCodeInstruction::kNotB);
+ this->write(ByteCodeInstruction::kMaskPush);
+ this->write(ByteCodeInstruction::kBranchIfAllFalse);
+ DeferredLocation falseLocation(this);
+ this->writeExpression(*b.fRight);
+ this->write(ByteCodeInstruction::kOrB);
+ falseLocation.set();
+ this->write(ByteCodeInstruction::kMaskPop);
+ return false;
+ }
+ default:
+ break;
+ }
this->writeExpression(*b.fRight);
if (lVecOrMtx && !rVecOrMtx) {
for (int i = SlotCount(lType); i > 1; --i) {
@@ -653,7 +685,6 @@
this->write8(lRows);
this->write8(rCols);
} else {
- int count = std::max(SlotCount(lType), SlotCount(rType));
switch (op) {
case Token::Kind::EQEQ:
this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
@@ -730,18 +761,10 @@
count);
break;
- case Token::Kind::LOGICALAND:
- SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
- this->write(ByteCodeInstruction::kAndB);
- break;
case Token::Kind::LOGICALNOT:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kNotB);
break;
- case Token::Kind::LOGICALOR:
- SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
- this->write(ByteCodeInstruction::kOrB);
- break;
case Token::Kind::LOGICALXOR:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kXorB);