Interpreter: Simplify interface quite a bit.

Slightly sharper, but far easier to hold:

- Remove Value union from interface, everything is a 32-bit
  value type, or a collection thereof.
- Collapse to one version of Run (that takes count), and make
  it a member on ByteCode.
- Similarly, move disassemble to ByteCodeFunction.

Change-Id: I07c85e65991178b3f52e20e815c25f36bc9c4257
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220753
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/bench/SkSLInterpreterBench.cpp b/bench/SkSLInterpreterBench.cpp
index c3a34cc..646d59f 100644
--- a/bench/SkSLInterpreterBench.cpp
+++ b/bench/SkSLInterpreterBench.cpp
@@ -6,8 +6,8 @@
  */
 #include "bench/Benchmark.h"
 #include "include/utils/SkRandom.h"
+#include "src/sksl/SkSLByteCode.h"
 #include "src/sksl/SkSLCompiler.h"
-#include "src/sksl/SkSLInterpreter.h"
 
 // Benchmarks the interpreter with a function that has a color-filter style signature
 class SkSLInterpreterCFBench : public Benchmark {
@@ -36,17 +36,15 @@
         fMain = fByteCode->getFunction("main");
 
         SkRandom rnd;
-        fPixels.resize(fCount);
-        for (int i = 0; i < fCount; ++i) {
-            fPixels[i] = SkColor4f::FromColor(rnd.nextU());
+        fPixels.resize(fCount * 4);
+        for (float& c : fPixels) {
+            c = rnd.nextF();
         }
     }
 
     void onDraw(int loops, SkCanvas*) override {
         for (int i = 0; i < loops; i++) {
-            SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
-                                      (SkSL::Interpreter::Value*)fPixels.data(), nullptr, fCount,
-                                      nullptr, 0);
+            fByteCode->run(fMain, fPixels.data(), nullptr, fCount, nullptr, 0);
         }
     }
 
@@ -57,7 +55,7 @@
     const SkSL::ByteCodeFunction* fMain;
 
     int fCount;
-    std::vector<SkColor4f> fPixels;
+    std::vector<float> fPixels;
 
     typedef Benchmark INHERITED;
 };
@@ -164,16 +162,12 @@
         fDst.resize(fGroups * fValues);
 
         SkRandom rnd;
-        for (auto& x : fSrc) {
-            x = rnd.nextS();
+        for (float& x : fSrc) {
+            x = rnd.nextF();
         }
 
         // Trigger one run now to check correctness
-        SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
-                                  (SkSL::Interpreter::Value*)fSrc.data(),
-                                  (SkSL::Interpreter::Value*)fDst.data(),
-                                  fGroups,
-                                  nullptr, 0);
+        fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
         for (int i = 0; i < fGroups; ++i) {
             for (int j = 1; j < fValues; ++j) {
                 SkASSERT(fDst[i * fValues + j] >= fDst[i * fValues + j - 1]);
@@ -183,11 +177,7 @@
 
     void onDraw(int loops, SkCanvas*) override {
         for (int i = 0; i < loops; i++) {
-            SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
-                                      (SkSL::Interpreter::Value*)fSrc.data(),
-                                      (SkSL::Interpreter::Value*)fDst.data(),
-                                      fGroups,
-                                      nullptr, 0);
+            fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
         }
     }
 
@@ -199,8 +189,8 @@
 
     int fGroups;
     int fValues;
-    std::vector<int32_t> fSrc;
-    std::vector<int32_t> fDst;
+    std::vector<float> fSrc;
+    std::vector<float> fDst;
 
     typedef Benchmark INHERITED;
 };
@@ -209,10 +199,10 @@
 // bounds checking.
 #if 0
 DEF_BENCH(return new SkSLInterpreterSortBench(1024, 32, R"(
-    int[32] main(int v[32]) {
+    float[32] main(float v[32]) {
         for (int i = 1; i < 32; ++i) {
             for (int j = i; j > 0 && v[j-1] > v[j]; --j) {
-                int t = v[j];
+                float t = v[j];
                 v[j] = v[j-1];
                 v[j-1] = t;
             }
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 3c12321..de369ef 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -8,6 +8,7 @@
 
 skia_sksl_sources = [
   "$_src/sksl/SkSLASTNode.cpp",
+  "$_src/sksl/SkSLByteCode.cpp",
   "$_src/sksl/SkSLByteCodeGenerator.cpp",
   "$_src/sksl/SkSLCFGGenerator.cpp",
   "$_src/sksl/SkSLCompiler.cpp",
@@ -15,7 +16,6 @@
   "$_src/sksl/SkSLCPPUniformCTypes.cpp",
   "$_src/sksl/SkSLGLSLCodeGenerator.cpp",
   "$_src/sksl/SkSLHCodeGenerator.cpp",
-  "$_src/sksl/SkSLInterpreter.cpp",
   "$_src/sksl/SkSLIRGenerator.cpp",
   "$_src/sksl/SkSLJIT.cpp",
   "$_src/sksl/SkSLLexer.cpp",
diff --git a/modules/particles/src/SkParticleAffector.cpp b/modules/particles/src/SkParticleAffector.cpp
index ab220883..0ed3ad1 100644
--- a/modules/particles/src/SkParticleAffector.cpp
+++ b/modules/particles/src/SkParticleAffector.cpp
@@ -17,9 +17,9 @@
 #include "src/core/SkMakeUnique.h"
 
 #if SK_SUPPORT_GPU
+#include "src/sksl/SkSLByteCode.h"
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
 #endif
 
 void SkParticleAffector::apply(const SkParticleUpdateParams& params,
@@ -481,8 +481,7 @@
     void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
         for (int i = 0; i < count; ++i) {
             fRandomValue->setRandom(&ps[i].fRandom);
-            SkSL::Interpreter::Run(fByteCode.get(), fMain, (SkSL::Interpreter::Value*)&ps[i].fAge,
-                                   nullptr, (SkSL::Interpreter::Value*)&params, 2);
+            fByteCode->run(fMain, &ps[i].fAge, nullptr, 1, &params.fDeltaTime, 2);
         }
     }
 
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index fa6cede..4a1bd13 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -366,7 +366,6 @@
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/effects/GrSkSLFP.h"
 #include "src/sksl/SkSLByteCode.h"
-#include "src/sksl/SkSLInterpreter.h"
 
 class SkRuntimeColorFilter : public SkColorFilter {
 public:
@@ -425,10 +424,8 @@
             ctx->main = ctx->byteCode->fFunctions[0].get();
             ctx->fn = [](SkRasterPipeline_CallbackCtx* arg, int active_pixels) {
                 auto ctx = (InterpreterCtx*)arg;
-                SkSL::Interpreter::VecRun(ctx->byteCode.get(), ctx->main,
-                                            (SkSL::Interpreter::Value*)ctx->rgba,
-                                            nullptr, active_pixels,
-                                            (SkSL::Interpreter::Value*)ctx->inputs, ctx->ninputs);
+                ctx->byteCode->run(ctx->main, ctx->rgba, nullptr, active_pixels,
+                                   (float*)ctx->inputs, ctx->ninputs);
             };
             rec.fPipeline->append(SkRasterPipeline::callback, ctx);
         }
diff --git a/src/sksl/SkSLInterpreter.cpp b/src/sksl/SkSLByteCode.cpp
similarity index 95%
rename from src/sksl/SkSLInterpreter.cpp
rename to src/sksl/SkSLByteCode.cpp
index 14a8206..739eed4 100644
--- a/src/sksl/SkSLInterpreter.cpp
+++ b/src/sksl/SkSLByteCode.cpp
@@ -12,7 +12,6 @@
 #include "src/sksl/SkSLByteCode.h"
 #include "src/sksl/SkSLByteCodeGenerator.h"
 #include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
 
 #include <vector>
 
@@ -241,15 +240,6 @@
     return ip;
 }
 
-void Disassemble(const ByteCodeFunction* f) {
-    const uint8_t* ip = f->fCode.data();
-    while (ip < f->fCode.data() + f->fCode.size()) {
-        printf("%d: ", (int) (ip - f->fCode.data()));
-        ip = disassemble_instruction(ip);
-        printf("\n");
-    }
-}
-
 #define VECTOR_BINARY_OP(base, field, op)                             \
     case ByteCodeInstruction::base ## 4:                              \
         sp[-4] = sp[-4].field op sp[0].field;                         \
@@ -361,8 +351,8 @@
     return a - skvx::trunc(a / b) * b;
 }
 
-void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack, Value* outReturn,
-              I32 initMask, VValue globals[], int globalCount) {
+void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
+              float* outReturn, I32 initMask, VValue globals[]) {
     VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
 
     auto POP =  [&]           { SkASSERT(sp     >= stack); return *(sp--); };
@@ -443,8 +433,8 @@
                 ExternalValue* v = byteCode->fExternalValues[target];
                 sp -= argumentCount - 1;
 
-                Value tmpArgs[4];
-                Value tmpReturn[4];
+                int32_t tmpArgs[4];
+                int32_t tmpReturn[4];
                 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
                 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
 
@@ -452,11 +442,11 @@
                 for (int i = 0; i < VecWidth; ++i) {
                     if (m[i]) {
                         for (int j = 0; j < argumentCount; ++j) {
-                            tmpArgs[j].fSigned = sp[j].fSigned[i];
+                            tmpArgs[j] = sp[j].fSigned[i];
                         }
                         v->call(tmpArgs, tmpReturn);
                         for (int j = 0; j < returnCount; ++j) {
-                            sp[j].fSigned[i] = tmpReturn[j].fSigned;
+                            sp[j].fSigned[i] = tmpReturn[j];
                         }
                     }
                 }
@@ -592,7 +582,6 @@
                 int src = READ8();
                 int count = READ8();
                 for (int i = 0; i < count; ++i) {
-                    SkASSERT(src + *(ip + i) < globalCount);
                     PUSH(globals[src + *(ip + i)]);
                 }
                 ip += count;
@@ -741,7 +730,7 @@
                         for (int i = 0; i < count; ++i) {
                             for (int j = 0; j < VecWidth; ++j) {
                                 if (m[j]) {
-                                    outReturn[count * j].fSigned = src->fSigned[j];
+                                    outReturn[count * j] = src->fFloat[j];
                                 }
                             }
                             ++outReturn;
@@ -983,59 +972,71 @@
     }
 }
 
-void VecRun(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
-            int N, Value uniforms[], int uniformCount) {
+} // namespace Interpreter
+
+void ByteCodeFunction::disassemble() const {
+    const uint8_t* ip = fCode.data();
+    while (ip < fCode.data() + fCode.size()) {
+        printf("%d: ", (int)(ip - fCode.data()));
+        ip = Interpreter::disassemble_instruction(ip);
+        printf("\n");
+    }
+}
+
+void ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
+                   const float* uniforms, int uniformCount) const {
 #ifdef TRACE
-    disassemble(f);
+    f->disassemble();
 #endif
-    VValue smallStack[128];
+    Interpreter::VValue smallStack[128];
 
     // Needs to be the first N non-negative integers, at least as large as VecWidth
-    static const I32 gLanes = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 };
+    static const Interpreter::I32 gLanes = {
+        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
+    };
 
-    SkASSERT(uniformCount == (int)byteCode->fInputSlots.size());
-    VValue smallGlobals[32];
-    VValue* globals = smallGlobals;
-    SkASSERT((int)SK_ARRAY_COUNT(smallGlobals) >= byteCode->fGlobalCount);
-    for (uint8_t slot : byteCode->fInputSlots) {
-        globals[slot].fUnsigned = (uniforms++)->fUnsigned;
+    SkASSERT(uniformCount == (int)fInputSlots.size());
+    Interpreter::VValue globals[32];
+    SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
+    for (uint8_t slot : fInputSlots) {
+        globals[slot].fFloat = *uniforms++;
     }
 
     while (N) {
-        VValue* stack = smallStack;
+        Interpreter::VValue* stack = smallStack;
 
-        int w = std::min(N, VecWidth);
+        int w = std::min(N, Interpreter::VecWidth);
         N -= w;
 
         // Transpose args into stack
         {
-            uint32_t* src = (uint32_t*)args;
+            float* src = args;
             for (int i = 0; i < w; ++i) {
-                uint32_t* dst = (uint32_t*)stack + i;
+                float* dst = (float*)stack + i;
                 for (int j = f->fParameterCount; j > 0; --j) {
                     *dst = *src++;
-                    dst += VecWidth;
+                    dst += Interpreter::VecWidth;
                 }
             }
         }
 
         auto mask = w > gLanes;
-        innerRun(byteCode, f, stack, outReturn, mask, globals, byteCode->fGlobalCount);
+        innerRun(this, f, stack, outReturn, mask, globals);
 
         // Transpose out parameters back
         {
-            uint32_t* dst = (uint32_t*)args;
+            float* dst = args;
             for (int i = 0; i < w; ++i) {
-                uint32_t* src = (uint32_t*)stack + i;
+                float* src = (float*)stack + i;
                 for (const auto& p : f->fParameters) {
                     if (p.fIsOutParameter) {
                         for (int j = p.fSlotCount; j > 0; --j) {
                             *dst++ = *src;
-                            src += VecWidth;
+                            src += Interpreter::VecWidth;
                         }
                     } else {
                         dst += p.fSlotCount;
-                        src += p.fSlotCount * VecWidth;
+                        src += p.fSlotCount * Interpreter::VecWidth;
                     }
                 }
             }
@@ -1046,12 +1047,6 @@
     }
 }
 
-void Run(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
-         Value uniforms[], int uniformCount) {
-    VecRun(byteCode, f, args, outReturn, 1, uniforms, uniformCount);
-}
-
-} // namespace Interpreter
 } // namespace SkSL
 
 #endif
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index 1a02152..518e16f 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -15,7 +15,6 @@
 
 namespace SkSL {
 
-struct ByteCode;
 class  ExternalValue;
 struct FunctionDeclaration;
 
@@ -159,6 +158,11 @@
     int fStackCount = 128;
     int fReturnCount = 0;
     std::vector<uint8_t> fCode;
+
+    /**
+     * Print bytecode disassembly to stdout.
+     */
+    void disassemble() const;
 };
 
 struct ByteCode {
@@ -166,6 +170,7 @@
     // one entry per input slot, contains the global slot to which the input slot maps
     std::vector<uint8_t> fInputSlots;
     std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
+    std::vector<ExternalValue*> fExternalValues;
 
     const ByteCodeFunction* getFunction(const char* name) const {
         for (const auto& f : fFunctions) {
@@ -176,7 +181,16 @@
         return nullptr;
     }
 
-    std::vector<ExternalValue*> fExternalValues;
+    /**
+     * Invokes the specified function with the given arguments, 'N' times.
+     * 'args', 'outReturn', and 'uniforms' are collections of 32-bit values (typically floats,
+     * but possibly int32_t or uint32_t, depending on the types used in the SkSL).
+     * Any 'out' or 'inout' parameters will result in the 'args' array being modified.
+     * The return value is stored in 'outReturn' (may be null, to discard the return value).
+     * 'uniforms' are mapped to 'uniform' globals, in order.
+     */
+    void run(const ByteCodeFunction*, float* args, float* outReturn, int N,
+             const float* uniforms, int uniformCount) const;
 };
 
 }
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 13ffc9e..9d779f2 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -5,8 +5,8 @@
  * found in the LICENSE file.
  */
 
+#include "include/private/SkFloatBits.h"
 #include "src/sksl/SkSLByteCodeGenerator.h"
-#include "src/sksl/SkSLInterpreter.h"
 
 #include <algorithm>
 
@@ -591,7 +591,7 @@
 
 void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
     this->write(ByteCodeInstruction::kPushImmediate);
-    this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
+    this->write32(SkFloat2Bits(f.fValue));
 }
 
 void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
@@ -659,8 +659,7 @@
             std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
             lvalue->load();
             this->write(ByteCodeInstruction::kPushImmediate);
-            this->write32(type_category(p.fType) == TypeCategory::kFloat
-                            ? Interpreter::Value(1.0f).fUnsigned : 1);
+            this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
             if (p.fOperator == Token::Kind::PLUSPLUS) {
                 this->writeTypedInstruction(p.fType,
                                             ByteCodeInstruction::kAddI,
@@ -704,8 +703,7 @@
                 this->write(ByteCodeInstruction::kDup);
             }
             this->write(ByteCodeInstruction::kPushImmediate);
-            this->write32(type_category(p.fType) == TypeCategory::kFloat
-                            ? Interpreter::Value(1.0f).fUnsigned : 1);
+            this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
             if (p.fOperator == Token::Kind::PLUSPLUS) {
                 this->writeTypedInstruction(p.fType,
                                             ByteCodeInstruction::kAddI,
diff --git a/src/sksl/SkSLExternalValue.h b/src/sksl/SkSLExternalValue.h
index 0cd4f19..08d57f9 100644
--- a/src/sksl/SkSLExternalValue.h
+++ b/src/sksl/SkSLExternalValue.h
@@ -8,7 +8,6 @@
 #ifndef SKSL_EXTERNALVALUE
 #define SKSL_EXTERNALVALUE
 
-#include "src/sksl/SkSLInterpreter.h"
 #include "src/sksl/ir/SkSLSymbol.h"
 
 namespace SkSL {
@@ -83,7 +82,7 @@
      * outResult must be a pointer to a region of sufficient size to hold the function's return
      * value.
      */
-    virtual void call(Interpreter::Value* arguments, Interpreter::Value* outResult) {
+    virtual void call(void* arguments, void* outResult) {
         SkASSERT(false);
     }
 
diff --git a/src/sksl/SkSLInterpreter.h b/src/sksl/SkSLInterpreter.h
deleted file mode 100644
index b9f0327..0000000
--- a/src/sksl/SkSLInterpreter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_INTERPRETER
-#define SKSL_INTERPRETER
-
-#include "src/sksl/SkSLDefines.h"
-
-namespace SkSL {
-
-struct ByteCode;
-struct ByteCodeFunction;
-
-namespace Interpreter {
-
-    union Value {
-        Value() {}
-
-        Value(float f)
-        : fFloat(f) {}
-
-        Value(int32_t s)
-        : fSigned(s) {}
-
-        Value(uint32_t u)
-        : fUnsigned(u) {}
-
-        Value(bool b)
-        : fBool(b) {}
-
-        float fFloat;
-        int32_t fSigned;
-        uint32_t fUnsigned;
-        bool fBool;
-    };
-
-    /**
-     * Invokes the specified function with the given arguments. 'out' and 'inout' parameters will
-     * result in the 'args' array being modified. The return value is stored in 'outReturn' (may be
-     * null, in which case the return value is discarded).
-     */
-    void Run(const ByteCode*, const ByteCodeFunction*, Value args[], Value* outReturn,
-             Value uniforms[], int uniformCount);
-
-    void VecRun(const ByteCode*, const ByteCodeFunction*, Value args[], Value* outReturn,
-                int N, Value uniforms[], int uniformCount);
-
-    /**
-     * Print bytecode disassembly to stdout.
-     */
-    void Disassemble(const ByteCodeFunction*);
-
-} // namespace Interpreter
-} // namespace SkSL
-
-#endif
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index d425ea8..4b67d09 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -6,15 +6,14 @@
  */
 
 #include "include/core/SkPoint3.h"
+#include "src/sksl/SkSLByteCode.h"
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
 #include "src/utils/SkJSON.h"
 
 #include "tests/Test.h"
 
-void test(skiatest::Reporter* r, const char* src, SkSL::Interpreter::Value* in, int expectedCount,
-          SkSL::Interpreter::Value* expected) {
+void test(skiatest::Reporter* r, const char* src, float* in, int expectedCount, float* expected) {
     SkSL::Compiler compiler;
     SkSL::Program::Settings settings;
     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
@@ -30,26 +29,25 @@
             return;
         }
         SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
-        std::unique_ptr<SkSL::Interpreter::Value[]> out =
-           std::unique_ptr<SkSL::Interpreter::Value[]>(new SkSL::Interpreter::Value[expectedCount]);
-        SkSL::Interpreter::Run(byteCode.get(), main, in, out.get(), nullptr, 0);
-        bool valid = !memcmp(out.get(), expected, sizeof(SkSL::Interpreter::Value) * expectedCount);
+        std::unique_ptr<float[]> out = std::unique_ptr<float[]>(new float[expectedCount]);
+        byteCode->run(main, in, out.get(), 1, nullptr, 0);
+        bool valid = !memcmp(out.get(), expected, sizeof(float) * expectedCount);
         if (!valid) {
             printf("for program: %s\n", src);
             printf("    expected (");
             const char* separator = "";
             for (int i = 0; i < expectedCount; ++i) {
-                printf("%s%f", separator, expected[i].fFloat);
+                printf("%s%f", separator, expected[i]);
                 separator = ", ";
             }
             printf("), but received (");
             separator = "";
             for (int i = 0; i < expectedCount; ++i) {
-                printf("%s%f", separator, out.get()[i].fFloat);
+                printf("%s%f", separator, out.get()[i]);
                 separator = ", ";
             }
             printf(")\n");
-            SkSL::Interpreter::Disassemble(main);
+            main->disassemble();
         }
         REPORTER_ASSERT(r, valid);
     } else {
@@ -64,56 +62,48 @@
                               7, 5, 8, 6,
                               6, 8, 5, 7 };
 
+    SkSL::Compiler compiler;
+    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
+            SkSL::Program::kGeneric_Kind, SkSL::String(src), SkSL::Program::Settings());
+    if (!program) {
+        REPORT_FAILURE(r, "!program", SkString(compiler.errorText().c_str()));
+        return;
+    }
+
+    std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
+    if (compiler.errorCount() > 0) {
+        REPORT_FAILURE(r, "!toByteCode", SkString(compiler.errorText().c_str()));
+        return;
+    }
+
+    const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
+
     float out_s[16], out_v[16];
     memcpy(out_s, input, sizeof(out_s));
     memcpy(out_v, input, sizeof(out_v));
 
-    for (int pass = 0; pass < 2; ++pass) {
-        SkSL::Compiler compiler;
-        std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
-                SkSL::Program::kGeneric_Kind, SkSL::String(src), SkSL::Program::Settings());
-        if (!program) {
-            REPORT_FAILURE(r, "!program", SkString(compiler.errorText().c_str()));
-            return;
-        }
+    // First run in scalar mode to determine the expected output
+    for (int i = 0; i < 4; ++i) {
+        byteCode->run(main, out_s + i * 4, nullptr, 1, nullptr, 0);
+    }
 
-        std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
-        if (compiler.errorCount() > 0) {
-            REPORT_FAILURE(r, "!toByteCode", SkString(compiler.errorText().c_str()));
-            return;
+    // Now run in parallel and compare results
+    byteCode->run(main, out_v, nullptr, 4, nullptr, 0);
+    if (memcmp(out_s, out_v, sizeof(out_s)) != 0) {
+        printf("for program: %s\n", src);
+        for (int i = 0; i < 4; ++i) {
+            printf("(%g %g %g %g) -> (%g %g %g %g), expected (%g %g %g %g)\n",
+                    input[4*i + 0], input[4*i + 1], input[4*i + 2], input[4*i + 3],
+                    out_v[4*i + 0], out_v[4*i + 1], out_v[4*i + 2], out_v[4*i + 3],
+                    out_s[4*i + 0], out_s[4*i + 1], out_s[4*i + 2], out_s[4*i + 3]);
         }
-
-        const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-
-        if (pass == 0) {
-            // First pass - run in scalar mode to determine the expected output
-            for (int i = 0; i < 4; ++i) {
-                SkSL::Interpreter::Run(byteCode.get(), main,
-                                       (SkSL::Interpreter::Value*)(out_s + i * 4), nullptr,
-                                       nullptr, 0);
-            }
-        } else {
-            // Second pass - run the vectorized interpreter and compare results
-            SkSL::Interpreter::VecRun(byteCode.get(), main,
-                                      (SkSL::Interpreter::Value*)out_v, nullptr, 4,
-                                      nullptr, 0);
-            if (memcmp(out_s, out_v, sizeof(out_s)) != 0) {
-                printf("for program: %s\n", src);
-                for (int i = 0; i < 4; ++i) {
-                    printf("(%g %g %g %g) -> (%g %g %g %g), expected (%g %g %g %g)\n",
-                           input[4*i + 0], input[4*i + 1], input[4*i + 2], input[4*i + 3],
-                           out_v[4*i + 0], out_v[4*i + 1], out_v[4*i + 2], out_v[4*i + 3],
-                           out_s[4*i + 0], out_s[4*i + 1], out_s[4*i + 2], out_s[4*i + 3]);
-                }
-                SkSL::Interpreter::Disassemble(main);
-                REPORT_FAILURE(r, "VecInterpreter mismatch", SkString());
-            }
-        }
+        main->disassemble();
+        REPORT_FAILURE(r, "VecInterpreter mismatch", SkString());
     }
 }
 
 void test(skiatest::Reporter* r, const char* src, float inR, float inG, float inB, float inA,
-        float expectedR, float expectedG, float expectedB, float expectedA) {
+          float expectedR, float expectedG, float expectedB, float expectedA) {
     SkSL::Compiler compiler;
     SkSL::Program::Settings settings;
     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
@@ -130,15 +120,14 @@
         }
         const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
         float inoutColor[4] = { inR, inG, inB, inA };
-        SkSL::Interpreter::Run(byteCode.get(), main, (SkSL::Interpreter::Value*) inoutColor,
-                               nullptr, nullptr, 0);
+        byteCode->run(main, inoutColor, nullptr, 1, nullptr, 0);
         if (inoutColor[0] != expectedR || inoutColor[1] != expectedG ||
             inoutColor[2] != expectedB || inoutColor[3] != expectedA) {
             printf("for program: %s\n", src);
             printf("    expected (%f, %f, %f, %f), but received (%f, %f, %f, %f)\n", expectedR,
                    expectedG, expectedB, expectedA, inoutColor[0], inoutColor[1], inoutColor[2],
                    inoutColor[3]);
-            SkSL::Interpreter::Disassemble(main);
+            main->disassemble();
         }
         REPORTER_ASSERT(r, inoutColor[0] == expectedR);
         REPORTER_ASSERT(r, inoutColor[1] == expectedG);
@@ -210,8 +199,8 @@
 }
 
 DEF_TEST(SkSLInterpreterMatrix, r) {
-    SkSL::Interpreter::Value in[16];
-    SkSL::Interpreter::Value expected[16];
+    float in[16];
+    float expected[16];
 
     // Constructing matrix from scalar produces a diagonal matrix
     in[0] = 1.0f;
@@ -291,7 +280,7 @@
     // M*M
     {
         SkMatrix44 m;
-        m.setColMajorf(&in[0].fFloat);
+        m.setColMajorf(in);
         SkMatrix44 m2;
         for (int i = 0; i < 16; ++i) {
             m2.set(i % 4, i / 4, (i + 4) % 16);
@@ -299,7 +288,7 @@
         m.setConcat(m, m2);
         // Rearrange the columns on the RHS so we detect left-hand/right-hand errors
         test(r, "float4x4 main(float4x4 m) { return m * float4x4(m[1], m[2], m[3], m[0]); }",
-             in, 16, (SkSL::Interpreter::Value*)&m);
+             in, 16, (float*)&m);
     }
 }
 
@@ -314,34 +303,40 @@
 }
 
 DEF_TEST(SkSLInterpreterCast, r) {
-    SkSL::Interpreter::Value input[2];
-    SkSL::Interpreter::Value expected[2];
+    union Val {
+        float    f;
+        uint32_t u;
+        int32_t  s;
+    };
 
-    input[0].fSigned = 3;
-    input[1].fSigned = -5;
-    expected[0].fFloat = 3.0f;
-    expected[1].fFloat = -5.0f;
-    test(r, "float  main(int  x) { return float (x); }", input, 1, expected);
-    test(r, "float2 main(int2 x) { return float2(x); }", input, 2, expected);
+    Val input[2];
+    Val expected[2];
 
-    input[0].fUnsigned = 3;
-    input[1].fUnsigned = 5;
-    expected[0].fFloat = 3.0f;
-    expected[1].fFloat = 5.0f;
-    test(r, "float  main(uint  x) { return float (x); }", input, 1, expected);
-    test(r, "float2 main(uint2 x) { return float2(x); }", input, 2, expected);
+    input[0].s = 3;
+    input[1].s = -5;
+    expected[0].f = 3.0f;
+    expected[1].f = -5.0f;
+    test(r, "float  main(int  x) { return float (x); }", (float*)input, 1, (float*)expected);
+    test(r, "float2 main(int2 x) { return float2(x); }", (float*)input, 2, (float*)expected);
 
-    input[0].fFloat = 3.0f;
-    input[1].fFloat = -5.0f;
-    expected[0].fSigned = 3;
-    expected[1].fSigned = -5;
-    test(r, "int  main(float  x) { return int (x); }", input, 1, expected);
-    test(r, "int2 main(float2 x) { return int2(x); }", input, 2, expected);
+    input[0].u = 3;
+    input[1].u = 5;
+    expected[0].f = 3.0f;
+    expected[1].f = 5.0f;
+    test(r, "float  main(uint  x) { return float (x); }", (float*)input, 1, (float*)expected);
+    test(r, "float2 main(uint2 x) { return float2(x); }", (float*)input, 2, (float*)expected);
 
-    input[0].fSigned = 3;
-    expected[0].fFloat = 3.0f;
-    expected[1].fFloat = 3.0f;
-    test(r, "float2 main(int x) { return float2(x); }", input, 2, expected);
+    input[0].f = 3.0f;
+    input[1].f = -5.0f;
+    expected[0].s = 3;
+    expected[1].s = -5;
+    test(r, "int  main(float  x) { return int (x); }", (float*)input, 1, (float*)expected);
+    test(r, "int2 main(float2 x) { return int2(x); }", (float*)input, 2, (float*)expected);
+
+    input[0].s = 3;
+    expected[0].f = 3.0f;
+    expected[1].f = 3.0f;
+    test(r, "float2 main(int x) { return float2(x); }", (float*)input, 2, (float*)expected);
 }
 
 DEF_TEST(SkSLInterpreterIf, r) {
@@ -469,13 +464,10 @@
 DEF_TEST(SkSLInterpreterGeneric, r) {
     float value1 = 5;
     float expected1 = 25;
-    test(r, "float main(float x) { return x * x; }", (SkSL::Interpreter::Value*) &value1, 1,
-         (SkSL::Interpreter::Value*) &expected1);
+    test(r, "float main(float x) { return x * x; }", &value1, 1, &expected1);
     float value2[2] = { 5, 25 };
     float expected2[2] = { 25, 625 };
-    test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }",
-         (SkSL::Interpreter::Value*) &value2, 2,
-         (SkSL::Interpreter::Value*) expected2);
+    test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }", value2, 2, expected2);
 }
 
 DEF_TEST(SkSLInterpreterCompound, r) {
@@ -548,20 +540,14 @@
     {
         SkIRect in = SkIRect::MakeXYWH(10, 10, 20, 30);
         int out = 0;
-        SkSL::Interpreter::Run(byteCode.get(), rect_height,
-                               (SkSL::Interpreter::Value*)&in,
-                               (SkSL::Interpreter::Value*)&out,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(rect_height, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
         REPORTER_ASSERT(r, out == 30);
     }
 
     {
         int in[2] = { 15, 25 };
         RectAndColor out;
-        SkSL::Interpreter::Run(byteCode.get(), make_blue_rect,
-                               (SkSL::Interpreter::Value*)in,
-                               (SkSL::Interpreter::Value*)&out,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(make_blue_rect, (float*)in, (float*)&out, 1, (float*)gRects, 16);
         REPORTER_ASSERT(r, out.fRect.width() == 15);
         REPORTER_ASSERT(r, out.fRect.height() == 25);
         SkColor4f blue = { 0.0f, 1.0f, 0.0f, 1.0f };
@@ -571,20 +557,14 @@
     {
         int in[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
         int out = 0;
-        SkSL::Interpreter::Run(byteCode.get(), median,
-                               (SkSL::Interpreter::Value*)in,
-                               (SkSL::Interpreter::Value*)&out,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(median, (float*)in, (float*)&out, 1, (float*)gRects, 16);
         REPORTER_ASSERT(r, out == 8);
     }
 
     {
         float in[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
         float out[8] = { 0 };
-        SkSL::Interpreter::Run(byteCode.get(), sums,
-                               (SkSL::Interpreter::Value*)in,
-                               (SkSL::Interpreter::Value*)out,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(sums, in, out, 1, (float*)gRects, 16);
         for (int i = 0; i < 8; ++i) {
             REPORTER_ASSERT(r, out[i] == static_cast<float>((i + 1) * (i + 2) / 2));
         }
@@ -593,10 +573,7 @@
     {
         int in = 2;
         SkIRect out = SkIRect::MakeEmpty();
-        SkSL::Interpreter::Run(byteCode.get(), get_rect,
-                               (SkSL::Interpreter::Value*)&in,
-                               (SkSL::Interpreter::Value*)&out,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(get_rect, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
         REPORTER_ASSERT(r, out == gRects[2]);
     }
 
@@ -604,10 +581,7 @@
         ManyRects in;
         memset(&in, 0, sizeof(in));
         in.fNumRects = 2;
-        SkSL::Interpreter::Run(byteCode.get(), fill_rects,
-                               (SkSL::Interpreter::Value*)&in,
-                               nullptr,
-                               (SkSL::Interpreter::Value*)gRects, 16);
+        byteCode->run(fill_rects, (float*)&in, nullptr, 1, (float*)gRects, 16);
         ManyRects expected;
         memset(&expected, 0, sizeof(expected));
         expected.fNumRects = 2;
@@ -663,27 +637,23 @@
 
     float out = 0.0f;
     float in = 3.0f;
-    SkSL::Interpreter::Run(byteCode.get(), main, (SkSL::Interpreter::Value*)&in,
-                           (SkSL::Interpreter::Value*)&out, nullptr, 0);
+    byteCode->run(main, &in, &out, 1, nullptr, 0);
     REPORTER_ASSERT(r, out = 6.0f);
 
-    SkSL::Interpreter::Run(byteCode.get(), dot3, (SkSL::Interpreter::Value*)&in,
-                           (SkSL::Interpreter::Value*)&out, nullptr, 0);
+    byteCode->run(dot3, &in, &out, 1, nullptr, 0);
     REPORTER_ASSERT(r, out = 9.0f);
 
-    SkSL::Interpreter::Run(byteCode.get(), dot2, (SkSL::Interpreter::Value*)&in,
-                           (SkSL::Interpreter::Value*)&out, nullptr, 0);
+    byteCode->run(dot2, &in, &out, 1, nullptr, 0);
     REPORTER_ASSERT(r, out = -1.0f);
 
     int fibIn = 6;
     int fibOut = 0;
-    SkSL::Interpreter::Run(byteCode.get(), fib, (SkSL::Interpreter::Value*)&fibIn,
-                           (SkSL::Interpreter::Value*)&fibOut, nullptr, 0);
+    byteCode->run(fib, (float*)&fibIn, (float*)&fibOut, 1, nullptr, 0);
     REPORTER_ASSERT(r, fibOut == 13);
 }
 
 DEF_TEST(SkSLInterpreterMathFunctions, r) {
-    SkSL::Interpreter::Value value, expected;
+    float value, expected;
 
     value = 0.0f; expected = 0.0f;
     test(r, "float main(float x) { return sin(x); }", &value, 1, &expected);
@@ -697,7 +667,7 @@
 }
 
 DEF_TEST(SkSLInterpreterMix, r) {
-    SkSL::Interpreter::Value value, expected;
+    float value, expected;
 
     value = 0.5f; expected = 0.0f;
     test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
@@ -706,39 +676,35 @@
     value = 2.0f; expected = 30.0f;
     test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
 
-    SkSL::Interpreter::Value valueVectors[]   = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
-                             expectedVector[] = { 3.0f, 4.0f, 5.0f, 6.0f };
+    float valueVectors[]   = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
+          expectedVector[] = { 3.0f, 4.0f, 5.0f, 6.0f };
     test(r, "float4 main(float4 x, float4 y) { return mix(x, y, 0.5); }", valueVectors, 4,
          expectedVector);
 }
 
 DEF_TEST(SkSLInterpreterCross, r) {
-    SkSL::Interpreter::Value args[] = { 1.0f, 4.0f, -6.0f, -2.0f, 7.0f, -3.0f };
-    SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(args[0].fFloat,
-                                                           args[1].fFloat,
-                                                           args[2].fFloat),
-                                            SkPoint3::Make(args[3].fFloat,
-                                                           args[4].fFloat,
-                                                           args[5].fFloat));
-    SkSL::Interpreter::Value expected[] = { cross.fX, cross.fY, cross.fZ };
+    float args[] = { 1.0f, 4.0f, -6.0f, -2.0f, 7.0f, -3.0f };
+    SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(args[0], args[1], args[2]),
+                                            SkPoint3::Make(args[3], args[4], args[5]));
+    float expected[] = { cross.fX, cross.fY, cross.fZ };
     test(r, "float3 main(float3 x, float3 y) { return cross(x, y); }", args, 3, expected);
 }
 
 DEF_TEST(SkSLInterpreterDot, r) {
-    SkSL::Interpreter::Value args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
-    SkSL::Interpreter::Value expected = args[0].fFloat * args[2].fFloat +
-                                        args[1].fFloat * args[3].fFloat;
+    float args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
+    float expected = args[0] * args[2] +
+                     args[1] * args[3];
     test(r, "float main(float2 x, float2 y) { return dot(x, y); }", args, 1, &expected);
 
-    expected = args[0].fFloat * args[3].fFloat +
-               args[1].fFloat * args[4].fFloat +
-               args[2].fFloat * args[5].fFloat;
+    expected = args[0] * args[3] +
+               args[1] * args[4] +
+               args[2] * args[5];
     test(r, "float main(float3 x, float3 y) { return dot(x, y); }", args, 1, &expected);
 
-    expected = args[0].fFloat * args[4].fFloat +
-               args[1].fFloat * args[5].fFloat +
-               args[2].fFloat * args[6].fFloat +
-               args[3].fFloat * args[7].fFloat;
+    expected = args[0] * args[4] +
+               args[1] * args[5] +
+               args[2] * args[6] +
+               args[3] * args[7];
     test(r, "float main(float4 x, float4 y) { return dot(x, y); }", args, 1, &expected);
 }
 
@@ -859,9 +825,9 @@
             return;
         }
         SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
-        SkSL::Interpreter::Value out;
-        SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
-        REPORTER_ASSERT(r, out.fFloat == 66.0);
+        float out;
+        byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+        REPORTER_ASSERT(r, out == 66.0);
         REPORTER_ASSERT(r, outValue == 152);
     } else {
         printf("%s\n%s", src, compiler.errorText().c_str());
@@ -892,8 +858,7 @@
             return;
         }
         SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
-        SkSL::Interpreter::Value out;
-        SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
+        byteCode->run(main, nullptr, nullptr, 1, nullptr, 0);
         REPORTER_ASSERT(r, value[0] == 2);
         REPORTER_ASSERT(r, value[1] == 4);
         REPORTER_ASSERT(r, value[2] == 6);
@@ -922,8 +887,8 @@
         outTypes[0] = fCompiler.context().fFloat_Type.get();
     }
 
-    void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
-        outReturn[0].fFloat = fFunction(arguments[0].fFloat);
+    void call(void* arguments, void* outReturn) override {
+        ((float*)outReturn)[0] = fFunction(((float*)arguments)[0]);
     }
 
 private:
@@ -958,9 +923,9 @@
             return;
         }
         SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
-        SkSL::Interpreter::Value out;
-        SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
-        REPORTER_ASSERT(r, out.fFloat == 5.0);
+        float out;
+        byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+        REPORTER_ASSERT(r, out == 5.0);
     } else {
         printf("%s\n%s", src, compiler.errorText().c_str());
     }
@@ -986,7 +951,7 @@
         outTypes[0] = fCompiler.context().fFloat4_Type.get();
     }
 
-    void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
+    void call(void* arguments, void* outReturn) override {
         fFunction((float*) arguments, (float*) outReturn);
     }
 
@@ -1026,12 +991,12 @@
             return;
         }
         SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
-        SkSL::Interpreter::Value out[4];
-        SkSL::Interpreter::Run(byteCode.get(), main, nullptr, out, nullptr, 0);
-        REPORTER_ASSERT(r, out[0].fFloat == 1.0);
-        REPORTER_ASSERT(r, out[1].fFloat == 2.0);
-        REPORTER_ASSERT(r, out[2].fFloat == 3.0);
-        REPORTER_ASSERT(r, out[3].fFloat == 4.0);
+        float out[4];
+        byteCode->run(main, nullptr, out, 1, nullptr, 0);
+        REPORTER_ASSERT(r, out[0] == 1.0);
+        REPORTER_ASSERT(r, out[1] == 2.0);
+        REPORTER_ASSERT(r, out[2] == 3.0);
+        REPORTER_ASSERT(r, out[3] == 4.0);
     } else {
         printf("%s\n%s", src, compiler.errorText().c_str());
     }