1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScript2.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define TypeOpName(op) {SkScriptEngine2::op, #op }
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const struct OpName {
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScriptEngine2::TypeOp fOp;
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fName;
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} gOpNames[] = {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kNop), // should never get generated
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kAccumulatorPop),
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kAccumulatorPush),
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kAddInt),
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kAddScalar),
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kAddString), // string concat
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kArrayIndex),
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kArrayParam),
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kArrayToken),
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kBitAndInt),
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kBitNotInt),
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kBitOrInt),
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kBoxToken),
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kCallback),
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kDivideInt),
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kDivideScalar),
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kDotOperator),
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kElseOp),
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kEnd),
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kEqualInt),
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kEqualScalar),
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kEqualString),
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kFunctionCall),
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kFlipOpsOp),
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kFunctionToken),
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kGreaterEqualInt),
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kGreaterEqualScalar),
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kGreaterEqualString),
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIfOp),
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntToScalar),
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntToScalar2),
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntToString),
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntToString2),
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntegerAccumulator),
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kIntegerOperand),
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kLogicalAndInt),
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kLogicalNotInt),
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kLogicalOrInt),
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kMemberOp),
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kMinusInt),
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kMinusScalar),
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kModuloInt),
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kModuloScalar),
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kMultiplyInt),
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kMultiplyScalar),
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kPropertyOp),
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarAccumulator),
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarOperand),
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarToInt),
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarToInt2),
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarToString),
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kScalarToString2),
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kShiftLeftInt),
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kShiftRightInt), // signed
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringAccumulator),
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringOperand),
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringToInt),
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringToScalar),
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringToScalar2),
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kStringTrack),
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kSubtractInt),
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kSubtractScalar),
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kToBool),
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kUnboxToken),
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kUnboxToken2),
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    TypeOpName(kXorInt)
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]);
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define OperandName(op) {SkOperand2::op, #op }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const struct OperName {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkOperand2::OpType fType;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* fName;
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} gOperandNames[] = {
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kNoType),
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kS32),
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kScalar),
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kString),
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kArray),
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    OperandName(kObject)
102d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com};
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// check to see that there are no missing or duplicate entries
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::ValidateDecompileTable() {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScriptEngine2::TypeOp op = SkScriptEngine2::kNop;
10964cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org    size_t index;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (index = 0; index < gOpNamesSize; index++) {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(gOpNames[index].fOp == op);
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        op = (SkScriptEngine2::TypeOp) (op + 1);
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    index = 0;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkOperand2::OpType type = SkOperand2::kNoType;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(gOperandNames[index].fType == type);
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (; index < gOperandNamesSize - 1; ) {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        type = (SkOperand2::OpType) (1 << index);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(gOperandNames[++index].fType == type);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::decompile(const unsigned char* start, size_t length) {
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(length > 0);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned char* opCode = start;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
12764cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org        SkASSERT((size_t)(opCode - start) < length);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++;
12964cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org        SkASSERT((size_t)op < gOpNamesSize);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("%d: %s", opCode - start - 1, gOpNames[op].fName);
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (op) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kCallback: {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int index;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&index, opCode, sizeof(index));
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(index);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" index: %d", index);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
138d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        case SkScriptEngine2::kFunctionCall:
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kMemberOp:
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kPropertyOp: {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            size_t ref;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&ref, opCode, sizeof(ref));
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(ref);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" ref: %d", ref);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kIntegerAccumulator:
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kIntegerOperand: {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int32_t integer;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&integer, opCode, sizeof(integer));
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(int32_t);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" integer: %d", integer);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kScalarAccumulator:
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kScalarOperand: {
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkScalar scalar;
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&scalar, opCode, sizeof(scalar));
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(SkScalar);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" scalar: %g", SkScalarToFloat(scalar));
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kStringAccumulator:
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kStringOperand: {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int size;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkString* strPtr = new SkString();
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&size, opCode, sizeof(size));
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(size);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strPtr->set((char*) opCode, size);
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += size;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" string: %s", strPtr->c_str());
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            delete strPtr;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kBoxToken: {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkOperand2::OpType type;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&type, opCode, sizeof(type));
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(type);
17564cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org            size_t index = 0;
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (type == 0)
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkDebugf(" type: %s", gOperandNames[index].fName);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            else {
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                while (type != 0) {
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkASSERT(index + 1 < gOperandNamesSize);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (type & (1 << index)) {
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        type = (SkOperand2::OpType) (type & ~(1 << index));
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkDebugf(" type: %s", gOperandNames[index + 1].fName);
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    index++;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kIfOp:
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kLogicalAndInt:
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kElseOp:
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kLogicalOrInt: {
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int size;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(&size, opCode, sizeof(size));
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            opCode += sizeof(size);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(" offset (address): %d (%d)", size, opCode - start + size);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } break;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kEnd:
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            goto done;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScriptEngine2::kNop:
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(0);
20264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org        default:
20364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org            break;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDebugf("\n");
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (true);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone:
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDebugf("\n");
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
212