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