Add new SkVM trace op 'trace_scope' to track SkSL scope depth.
This CL adds the trace op and tests the builder commands, but it is not
yet hooked up to the SkVM code generator or debugger.
Change-Id: Iaa64293dfd0973e299eb480cb2b43672b0886c32
Bug: skia:12741
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/484439
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/src/core/SkVM.cpp b/src/core/SkVM.cpp
index 20093e9..5aecf33 100644
--- a/src/core/SkVM.cpp
+++ b/src/core/SkVM.cpp
@@ -276,6 +276,7 @@
VarSlot{immB}, "=", V{z}); break;
case Op::trace_enter: write(o, op, TraceHookID{immA}, V{x}, V{y}, FnIdx{immB}); break;
case Op::trace_exit: write(o, op, TraceHookID{immA}, V{x}, V{y}, FnIdx{immB}); break;
+ case Op::trace_scope: write(o, op, TraceHookID{immA}, V{x}, V{y}, Shift{immB}); break;
case Op::store8: write(o, op, Ptr{immA}, V{x} ); break;
case Op::store16: write(o, op, Ptr{immA}, V{x} ); break;
@@ -402,6 +403,8 @@
R{x}, R{y}, FnIdx{immB}); break;
case Op::trace_exit: write(o, op, TraceHookID{immA},
R{x}, R{y}, FnIdx{immB}); break;
+ case Op::trace_scope: write(o, op, TraceHookID{immA},
+ R{x}, R{y}, Shift{immB}); break;
case Op::store8: write(o, op, Ptr{immA}, R{x} ); break;
case Op::store16: write(o, op, Ptr{immA}, R{x} ); break;
@@ -685,6 +688,15 @@
if (this->isImm(traceMask.id,~0)) { traceMask = mask; }
(void)push(Op::trace_exit, mask.id,traceMask.id,NA,NA, traceHookID, fnIdx);
}
+ void Builder::trace_scope(int traceHookID, I32 mask, I32 traceMask, int delta) {
+ SkASSERT(traceHookID >= 0);
+ SkASSERT(traceHookID < (int)fTraceHooks.size());
+ if (this->isImm(mask.id, 0)) { return; }
+ if (this->isImm(traceMask.id, 0)) { return; }
+ if (this->isImm(mask.id, ~0)) { mask = traceMask; }
+ if (this->isImm(traceMask.id,~0)) { traceMask = mask; }
+ (void)push(Op::trace_scope, mask.id,traceMask.id,NA,NA, traceHookID, delta);
+ }
void Builder::store8 (Ptr ptr, I32 val) { (void)push(Op::store8 , val.id,NA,NA,NA, ptr.ix); }
void Builder::store16(Ptr ptr, I32 val) { (void)push(Op::store16, val.id,NA,NA,NA, ptr.ix); }
@@ -2673,6 +2685,7 @@
case Op::trace_var:
case Op::trace_enter:
case Op::trace_exit:
+ case Op::trace_scope:
/* Force this program to run in the interpreter. */
return false;
@@ -3611,6 +3624,7 @@
case Op::trace_var:
case Op::trace_enter:
case Op::trace_exit:
+ case Op::trace_scope:
/* Force this program to run in the interpreter. */
return false;
@@ -3984,6 +3998,7 @@
case Op::trace_var:
case Op::trace_enter:
case Op::trace_exit:
+ case Op::trace_scope:
/* Force this program to run in the interpreter. */
return false;
diff --git a/src/core/SkVM.h b/src/core/SkVM.h
index ed499e7..c0079db 100644
--- a/src/core/SkVM.h
+++ b/src/core/SkVM.h
@@ -434,7 +434,8 @@
// Order matters a little: Ops <=store128 are treated as having side effects.
#define SKVM_OPS(M) \
M(assert_true) \
- M(trace_line) M(trace_var) M(trace_enter) M(trace_exit) \
+ M(trace_line) M(trace_var) \
+ M(trace_enter) M(trace_exit) M(trace_scope) \
M(store8) M(store16) M(store32) M(store64) M(store128) \
M(load8) M(load16) M(load32) M(load64) M(load128) \
M(index) \
@@ -475,7 +476,7 @@
return Op::store8 <= op && op <= Op::index;
}
static inline bool is_trace(Op op) {
- return Op::trace_line <= op && op <= Op::trace_exit;
+ return Op::trace_line <= op && op <= Op::trace_scope;
}
using Val = int;
@@ -612,6 +613,7 @@
virtual void var(int slot, int32_t val) = 0;
virtual void enter(int fnIdx) = 0;
virtual void exit(int fnIdx) = 0;
+ virtual void scope(int delta) = 0;
};
class Builder {
@@ -649,6 +651,7 @@
void trace_var (int traceHookID, I32 mask, I32 traceMask, int slot, I32 val);
void trace_enter(int traceHookID, I32 mask, I32 traceMask, int fnIdx);
void trace_exit (int traceHookID, I32 mask, I32 traceMask, int fnIdx);
+ void trace_scope(int traceHookID, I32 mask, I32 traceMask, int delta);
// Store {8,16,32,64,128}-bit varying.
void store8 (Ptr ptr, I32 val);
diff --git a/src/opts/SkVM_opts.h b/src/opts/SkVM_opts.h
index 1db89cd..6038aba 100644
--- a/src/opts/SkVM_opts.h
+++ b/src/opts/SkVM_opts.h
@@ -250,6 +250,12 @@
}
break;
+ CASE(Op::trace_scope):
+ if (should_trace(immA, x, y)) {
+ traceHooks[immA]->scope(immB);
+ }
+ break;
+
CASE(Op::index): {
const int iota[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
diff --git a/src/sksl/codegen/SkSLVMCodeGenerator.cpp b/src/sksl/codegen/SkSLVMCodeGenerator.cpp
index cf115d0..d3ed1f1 100644
--- a/src/sksl/codegen/SkSLVMCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLVMCodeGenerator.cpp
@@ -82,12 +82,15 @@
fTrace->fTraceInfo.push_back({SkSL::SkVMTraceInfo::Op::kExit,
/*data=*/{fnIdx, 0}});
}
+ void scope(int delta) override {
+ fTrace->fTraceInfo.push_back({SkSL::SkVMTraceInfo::Op::kScope,
+ /*data=*/{delta, 0}});
+ }
private:
SkSL::SkVMDebugTrace* fTrace;
};
-}
-
+} // namespace
namespace SkSL {
diff --git a/src/sksl/tracing/SkVMDebugTrace.cpp b/src/sksl/tracing/SkVMDebugTrace.cpp
index f15ef9e..88dedc9 100644
--- a/src/sksl/tracing/SkVMDebugTrace.cpp
+++ b/src/sksl/tracing/SkVMDebugTrace.cpp
@@ -153,6 +153,19 @@
o->writeText("exit ");
o->writeText(fFuncInfo[data0].name.c_str());
break;
+
+ case SkSL::SkVMTraceInfo::Op::kScope:
+ for (int delta = data0; delta < 0; ++delta) {
+ indent.pop_back();
+ }
+ o->writeText(indent.c_str());
+ o->writeText("scope ");
+ o->writeText((data0 >= 0) ? "+" : "");
+ o->writeDecAsText(data0);
+ for (int delta = data0; delta > 0; --delta) {
+ indent.push_back(' ');
+ }
+ break;
}
o->newline();
}
diff --git a/src/sksl/tracing/SkVMDebugTrace.h b/src/sksl/tracing/SkVMDebugTrace.h
index 40bfef4..3a0792c 100644
--- a/src/sksl/tracing/SkVMDebugTrace.h
+++ b/src/sksl/tracing/SkVMDebugTrace.h
@@ -47,6 +47,7 @@
kVar, /** data: slot, value */
kEnter, /** data: function index, (unused) */
kExit, /** data: function index, (unused) */
+ kScope, /** data: scope delta, (unused) */
};
Op op;
int32_t data[2];
diff --git a/src/sksl/tracing/SkVMDebugTracePlayer.cpp b/src/sksl/tracing/SkVMDebugTracePlayer.cpp
index cdaae4e..7b76f70 100644
--- a/src/sksl/tracing/SkVMDebugTracePlayer.cpp
+++ b/src/sksl/tracing/SkVMDebugTracePlayer.cpp
@@ -193,6 +193,10 @@
fStack.pop_back();
return true;
}
+ case SkVMTraceInfo::Op::kScope: { // data: scope delta, (unused)
+ // TODO(skia:12741): track scope depth of variables
+ return false;
+ }
}
return false;
diff --git a/tests/SkVMTest.cpp b/tests/SkVMTest.cpp
index 199f275..547efa4 100644
--- a/tests/SkVMTest.cpp
+++ b/tests/SkVMTest.cpp
@@ -886,6 +886,7 @@
void var(int, int32_t) override { fBuffer.push_back(-9999999); }
void enter(int) override { fBuffer.push_back(-9999999); }
void exit(int) override { fBuffer.push_back(-9999999); }
+ void scope(int) override { fBuffer.push_back(-9999999); }
void line(int lineNum) override { fBuffer.push_back(lineNum); }
std::vector<int> fBuffer;
@@ -911,6 +912,7 @@
void line(int) override { fBuffer.push_back(-9999999); }
void enter(int) override { fBuffer.push_back(-9999999); }
void exit(int) override { fBuffer.push_back(-9999999); }
+ void scope(int) override { fBuffer.push_back(-9999999); }
void var(int slot, int32_t val) override {
fBuffer.push_back(slot);
fBuffer.push_back(val);
@@ -938,6 +940,7 @@
public:
void line(int) override { fBuffer.push_back(-9999999); }
void var(int, int32_t) override { fBuffer.push_back(-9999999); }
+ void scope(int) override { fBuffer.push_back(-9999999); }
void enter(int fnIdx) override {
fBuffer.push_back(fnIdx);
fBuffer.push_back(1);
@@ -965,12 +968,39 @@
REPORTER_ASSERT(r, (testTrace.fBuffer == std::vector<int>{12, 1, 56, 0}));
}
+DEF_TEST(SkVM_trace_scope, r) {
+ class TestTraceHook : public skvm::TraceHook {
+ public:
+ void var(int, int32_t) override { fBuffer.push_back(-9999999); }
+ void enter(int) override { fBuffer.push_back(-9999999); }
+ void exit(int) override { fBuffer.push_back(-9999999); }
+ void line(int) override { fBuffer.push_back(-9999999); }
+ void scope(int delta) override { fBuffer.push_back(delta); }
+
+ std::vector<int> fBuffer;
+ };
+
+ skvm::Builder b;
+ TestTraceHook testTrace;
+ int traceHookID = b.attachTraceHook(&testTrace);
+ b.trace_scope(traceHookID, b.splat(0xFFFFFFFF), b.splat(0xFFFFFFFF), 1);
+ b.trace_scope(traceHookID, b.splat(0xFFFFFFFF), b.splat(0x00000000), -2);
+ b.trace_scope(traceHookID, b.splat(0x00000000), b.splat(0x00000000), 3);
+ b.trace_scope(traceHookID, b.splat(0x00000000), b.splat(0xFFFFFFFF), 4);
+ b.trace_scope(traceHookID, b.splat(0xFFFFFFFF), b.splat(0xFFFFFFFF), -5);
+ skvm::Program p = b.done();
+ p.eval(1);
+
+ REPORTER_ASSERT(r, (testTrace.fBuffer == std::vector<int>{1, -5}));
+}
+
DEF_TEST(SkVM_trace_multiple_hooks, r) {
class TestTraceHook : public skvm::TraceHook {
public:
void var(int, int32_t) override { fBuffer.push_back(-9999999); }
void enter(int) override { fBuffer.push_back(-9999999); }
void exit(int) override { fBuffer.push_back(-9999999); }
+ void scope(int) override { fBuffer.push_back(-9999999); }
void line(int lineNum) override { fBuffer.push_back(lineNum); }
std::vector<int> fBuffer;