careful constants map handling

Setting up the Windows JIT made me notice that we can
modify the constants SkTHashMap while using it, e.g.

   a->vfmaddps132(dst(x), reg(y), any(z))

if any() returns a Label* Operand pointing to a constant, and
reg() needs to load from a constant too, and the second to touch
the constants map causes a hash table resize, the other is left
with a Label* that's pointing into the old table.

The fix is to (mostly) never modify the constants table when
looking up constants, instead using the Op::splat to seed the
table.  A couple miscellaneous constants like 0xffff'ffff as
used by assert_true are not dangerous so I've left them alone.

This is the sort of bug ASAN would catch, except we turn off
the JIT when building for ASAN.  I think I can tighten that up
so that we still JIT under ASAN, but never use the JIT'd code.
That'd let us catch bugs like this in the JIT itself.

Change-Id: I91d8f6fda721a6e3c9e3629d694a73fd1b2bf8f1
Reviewed-by: Herb Derby <>
Commit-Queue: Mike Klein <>
diff --git a/src/core/SkVM.cpp b/src/core/SkVM.cpp
index 654ab8f..66fb40e 100644
--- a/src/core/SkVM.cpp
+++ b/src/core/SkVM.cpp
@@ -2789,7 +2789,7 @@
                 if (instructions[v].immy == 0) {
                 } else {
-                    a->vmovups(r, &constants[instructions[v].immy]);
+                    a->vmovups(r, constants.find(instructions[v].immy));
             } else {
                 SkASSERT(stack_slot[v] != NA);
@@ -2821,7 +2821,7 @@
                 if (instructions[v].immy == 0) {
                 } else {
-                    a->ldrq(r, &constants[instructions[v].immy]);
+                    a->ldrq(r, constants.find(instructions[v].immy));
             } else {
                 SkASSERT(stack_slot[v] != NA);
@@ -2982,7 +2982,7 @@
                     return (Reg)found;
                 if (instructions[v].op == Op::splat) {
-                    return &constants[instructions[v].immy];
+                    return constants.find(instructions[v].immy);
                 return A::Mem{A::rsp, stack_slot[v]*K*4};
@@ -2995,8 +2995,10 @@
             switch (op) {
-                // Splats are handled above.
-                case Op::splat: break;
+                case Op::splat:
+                    // Make sure splat constants can be found by load_from_memory() or any().
+                    (void)constants[immy];
+                    break;
             #if defined(__x86_64__)
                 case Op::assert_true: {