Report slot updates using a dirty mask.

By tracking slot writes using a dirty mask, and reporting these in the
VariableData, we will be able to highlight assigned-to variables in the
debugger.

Change-Id: I93a767095c9c1b6dedc55a08424649f83aa1c960
Bug: skia:12666
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/483598
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-12-13 13:39:34 -05:00 committed by SkCQ
parent e4bccab4ac
commit 9247feb52c
3 changed files with 40 additions and 29 deletions

View File

@ -19,9 +19,11 @@ void SkVMDebugTracePlayer::reset(sk_sp<SkVMDebugTrace> debugTrace) {
fStack.push_back({/*fFunction=*/-1,
/*fLine=*/-1,
/*fDisplayMask=*/SkBitSet(nslots)});
fDirtyMask.emplace(nslots);
}
void SkVMDebugTracePlayer::step() {
fDirtyMask->reset();
while (!this->traceHasCompleted()) {
if (this->execute(fCursor++)) {
break;
@ -30,6 +32,7 @@ void SkVMDebugTracePlayer::step() {
}
void SkVMDebugTracePlayer::stepOver() {
fDirtyMask->reset();
size_t initialStackDepth = fStack.size();
while (!this->traceHasCompleted()) {
bool canEscapeFromThisStackDepth = (fStack.size() <= initialStackDepth);
@ -40,6 +43,7 @@ void SkVMDebugTracePlayer::stepOver() {
}
void SkVMDebugTracePlayer::stepOut() {
fDirtyMask->reset();
size_t initialStackDepth = fStack.size();
while (!this->traceHasCompleted()) {
if (this->execute(fCursor++) && (fStack.size() < initialStackDepth)) {
@ -78,7 +82,7 @@ std::vector<SkVMDebugTracePlayer::VariableData> SkVMDebugTracePlayer::getVariabl
std::vector<VariableData> vars;
bits.forEachSetIndex([&](int slot) {
vars.push_back({slot, fSlots[slot]});
vars.push_back({slot, fDirtyMask->test(slot), fSlots[slot]});
});
return vars;
}
@ -134,6 +138,7 @@ bool SkVMDebugTracePlayer::execute(size_t position) {
SkASSERT(fStack.size() > 1);
fStack.rbegin()[1].fDisplayMask.set(slot);
}
fDirtyMask->set(slot);
break;
}
case SkVMTraceInfo::Op::kEnter: { // data: function index, (unused)

View File

@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
#include "include/private/SkTOptional.h"
#include "src/sksl/tracing/SkVMDebugTrace.h"
#include "src/utils/SkBitSet.h"
@ -45,6 +46,7 @@ public:
/** Returns variables from a stack frame, or from global scope. */
struct VariableData {
int fSlotIndex;
bool fDirty; // has this slot been written-to since the last step call?
int32_t fValue; // caller must type-pun bits to float/bool based on slot type
};
std::vector<VariableData> getLocalVariables(int stackFrameIndex) const;
@ -69,6 +71,8 @@ private:
size_t fCursor = 0; // position of the read head
std::vector<int32_t> fSlots; // values in each slot
std::vector<StackFrame> fStack; // the execution stack
skstd::optional<SkBitSet> fDirtyMask; // variable slots touched during the most-recently
// executed step
};
} // namespace SkSL

View File

@ -70,6 +70,7 @@ static std::string make_vars_string(
}
const SkSL::SkVMSlotInfo& slot = trace.fSlotInfo[var.fSlotIndex];
text += var.fDirty ? "##": "";
text += slot.name;
text += trace.getSlotComponentSuffix(var.fSlotIndex);
text += " = ";
@ -150,7 +151,7 @@ int main() { // Line 2
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, player.getCurrentLine() == -1);
REPORTER_ASSERT(r, player.getCallStack().empty());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
}
DEF_TEST(SkSLTracePlayerReset, r) {
@ -227,7 +228,7 @@ int main() { // Line 8
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, player.getCurrentLine() == -1);
REPORTER_ASSERT(r, player.getCallStack().empty());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
// Watch the stack grow and shrink as single-step.
player.reset(trace);
@ -249,17 +250,17 @@ int main() { // Line 8
player.step();
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fnA()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "[fnB].result = 4");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fnB].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
player.step();
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "[fnA].result = 4");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fnA].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "");
player.step();
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
}
DEF_TEST(SkSLTracePlayerVariables, r) {
@ -290,12 +291,12 @@ int main() { // Line 6
REPORTER_ASSERT(r, player.getCurrentLine() == 8);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 123");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 123");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 9);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 123, b = true");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 123, ##b = true");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 3);
@ -305,7 +306,7 @@ int main() { // Line 6
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> void func()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "z = 456");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##z = 456");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 9);
@ -321,22 +322,23 @@ int main() { // Line 6
REPORTER_ASSERT(r, player.getCurrentLine() == 11);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
"a = 123, b = true, c.x = 0.000000, c.y = 0.500000, c.z = 1.000000, "
"c.w = -1.000000");
"a = 123, b = true, ##c.x = 0.000000, ##c.y = 0.500000, ##c.z = 1.000000, "
"##c.w = -1.000000");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 12);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) ==
"a = 123, b = true, c.x = 0.000000, c.y = 0.500000, c.z = 1.000000, "
"c.w = -1.000000, d[0][0] = 2.000000, d[0][1] = 0.000000, d[0][2] = 0.000000, "
"d[1][0] = 0.000000, d[1][1] = 2.000000, d[1][2] = 0.000000, "
"d[2][0] = 0.000000, d[2][1] = 0.000000, d[2][2] = 2.000000");
"c.w = -1.000000, ##d[0][0] = 2.000000, ##d[0][1] = 0.000000, "
"##d[0][2] = 0.000000, ##d[1][0] = 0.000000, ##d[1][1] = 2.000000, "
"##d[1][2] = 0.000000, ##d[2][0] = 0.000000, ##d[2][1] = 0.000000, "
"##d[2][2] = 2.000000");
player.step();
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 123");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 123");
}
DEF_TEST(SkSLTracePlayerIfStatement, r) {
@ -367,7 +369,7 @@ int main() { // Line 2
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 0");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 5);
@ -376,7 +378,7 @@ int main() { // Line 2
// We skip over the false-branch.
REPORTER_ASSERT(r, player.getCurrentLine() == 9);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 1");
player.step();
// We skip over the true-branch.
@ -385,11 +387,11 @@ int main() { // Line 2
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 14);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 4");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 4");
player.step();
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 4");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 4");
}
DEF_TEST(SkSLTracePlayerForLoop, r) {
@ -413,23 +415,23 @@ int main() { // Line 2
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 0");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 5);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0, x = 1");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 0, ##x = 1");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1, x = 1");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 1, x = 1");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 5);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1, x = 2");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 1, ##x = 2");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "val = 2, x = 2");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##val = 2, x = 2");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 7);
@ -437,7 +439,7 @@ int main() { // Line 2
player.step();
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 2");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 2");
}
DEF_TEST(SkSLTracePlayerStepOut, r) {
@ -471,20 +473,20 @@ int main() { // Line 9
REPORTER_ASSERT(r, player.getCurrentLine() == 4);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fn()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 11");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##a = 11");
player.step();
REPORTER_ASSERT(r, player.getCurrentLine() == 5);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main() -> int fn()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 11, b = 22");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "a = 11, ##b = 22");
player.stepOut();
// We should now be back inside main(), right where we left off.
REPORTER_ASSERT(r, player.getCurrentLine() == 10);
REPORTER_ASSERT(r, make_stack_string(*trace, player) == "int main()");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "[fn].result = 44");
REPORTER_ASSERT(r, make_local_vars_string(*trace, player) == "##[fn].result = 44");
player.stepOut();
REPORTER_ASSERT(r, player.traceHasCompleted());
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "[main].result = 44");
REPORTER_ASSERT(r, make_global_vars_string(*trace, player) == "##[main].result = 44");
}