1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkScript2.h"
11
12#ifdef SK_DEBUG
13
14#define TypeOpName(op) {SkScriptEngine2::op, #op }
15
16static const struct OpName {
17    SkScriptEngine2::TypeOp fOp;
18    const char* fName;
19} gOpNames[] = {
20    TypeOpName(kNop), // should never get generated
21    TypeOpName(kAccumulatorPop),
22    TypeOpName(kAccumulatorPush),
23    TypeOpName(kAddInt),
24    TypeOpName(kAddScalar),
25    TypeOpName(kAddString), // string concat
26    TypeOpName(kArrayIndex),
27    TypeOpName(kArrayParam),
28    TypeOpName(kArrayToken),
29    TypeOpName(kBitAndInt),
30    TypeOpName(kBitNotInt),
31    TypeOpName(kBitOrInt),
32    TypeOpName(kBoxToken),
33    TypeOpName(kCallback),
34    TypeOpName(kDivideInt),
35    TypeOpName(kDivideScalar),
36    TypeOpName(kDotOperator),
37    TypeOpName(kElseOp),
38    TypeOpName(kEnd),
39    TypeOpName(kEqualInt),
40    TypeOpName(kEqualScalar),
41    TypeOpName(kEqualString),
42    TypeOpName(kFunctionCall),
43    TypeOpName(kFlipOpsOp),
44    TypeOpName(kFunctionToken),
45    TypeOpName(kGreaterEqualInt),
46    TypeOpName(kGreaterEqualScalar),
47    TypeOpName(kGreaterEqualString),
48    TypeOpName(kIfOp),
49    TypeOpName(kIntToScalar),
50    TypeOpName(kIntToScalar2),
51    TypeOpName(kIntToString),
52    TypeOpName(kIntToString2),
53    TypeOpName(kIntegerAccumulator),
54    TypeOpName(kIntegerOperand),
55    TypeOpName(kLogicalAndInt),
56    TypeOpName(kLogicalNotInt),
57    TypeOpName(kLogicalOrInt),
58    TypeOpName(kMemberOp),
59    TypeOpName(kMinusInt),
60    TypeOpName(kMinusScalar),
61    TypeOpName(kModuloInt),
62    TypeOpName(kModuloScalar),
63    TypeOpName(kMultiplyInt),
64    TypeOpName(kMultiplyScalar),
65    TypeOpName(kPropertyOp),
66    TypeOpName(kScalarAccumulator),
67    TypeOpName(kScalarOperand),
68    TypeOpName(kScalarToInt),
69    TypeOpName(kScalarToInt2),
70    TypeOpName(kScalarToString),
71    TypeOpName(kScalarToString2),
72    TypeOpName(kShiftLeftInt),
73    TypeOpName(kShiftRightInt), // signed
74    TypeOpName(kStringAccumulator),
75    TypeOpName(kStringOperand),
76    TypeOpName(kStringToInt),
77    TypeOpName(kStringToScalar),
78    TypeOpName(kStringToScalar2),
79    TypeOpName(kStringTrack),
80    TypeOpName(kSubtractInt),
81    TypeOpName(kSubtractScalar),
82    TypeOpName(kToBool),
83    TypeOpName(kUnboxToken),
84    TypeOpName(kUnboxToken2),
85    TypeOpName(kXorInt)
86};
87
88static size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]);
89
90#define OperandName(op) {SkOperand2::op, #op }
91
92static const struct OperName {
93    SkOperand2::OpType fType;
94    const char* fName;
95} gOperandNames[] = {
96    OperandName(kNoType),
97    OperandName(kS32),
98    OperandName(kScalar),
99    OperandName(kString),
100    OperandName(kArray),
101    OperandName(kObject)
102};
103
104static size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]);
105
106// check to see that there are no missing or duplicate entries
107void SkScriptEngine2::ValidateDecompileTable() {
108    SkScriptEngine2::TypeOp op = SkScriptEngine2::kNop;
109    size_t index;
110    for (index = 0; index < gOpNamesSize; index++) {
111        SkASSERT(gOpNames[index].fOp == op);
112        op = (SkScriptEngine2::TypeOp) (op + 1);
113    }
114    index = 0;
115    SkOperand2::OpType type = SkOperand2::kNoType;
116    SkASSERT(gOperandNames[index].fType == type);
117    for (; index < gOperandNamesSize - 1; ) {
118        type = (SkOperand2::OpType) (1 << index);
119        SkASSERT(gOperandNames[++index].fType == type);
120    }
121}
122
123void SkScriptEngine2::decompile(const unsigned char* start, size_t length) {
124    SkASSERT(length > 0);
125    const unsigned char* opCode = start;
126    do {
127        SkASSERT((size_t)(opCode - start) < length);
128        SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++;
129        SkASSERT((size_t)op < gOpNamesSize);
130        SkDebugf("%d: %s", opCode - start - 1, gOpNames[op].fName);
131        switch (op) {
132        case SkScriptEngine2::kCallback: {
133            int index;
134            memcpy(&index, opCode, sizeof(index));
135            opCode += sizeof(index);
136            SkDebugf(" index: %d", index);
137            } break;
138        case SkScriptEngine2::kFunctionCall:
139        case SkScriptEngine2::kMemberOp:
140        case SkScriptEngine2::kPropertyOp: {
141            size_t ref;
142            memcpy(&ref, opCode, sizeof(ref));
143            opCode += sizeof(ref);
144            SkDebugf(" ref: %d", ref);
145            } break;
146        case SkScriptEngine2::kIntegerAccumulator:
147        case SkScriptEngine2::kIntegerOperand: {
148            int32_t integer;
149            memcpy(&integer, opCode, sizeof(integer));
150            opCode += sizeof(int32_t);
151            SkDebugf(" integer: %d", integer);
152            } break;
153        case SkScriptEngine2::kScalarAccumulator:
154        case SkScriptEngine2::kScalarOperand: {
155            SkScalar scalar;
156            memcpy(&scalar, opCode, sizeof(scalar));
157            opCode += sizeof(SkScalar);
158            SkDebugf(" scalar: %g", SkScalarToFloat(scalar));
159            } break;
160        case SkScriptEngine2::kStringAccumulator:
161        case SkScriptEngine2::kStringOperand: {
162            int size;
163            SkString* strPtr = new SkString();
164            memcpy(&size, opCode, sizeof(size));
165            opCode += sizeof(size);
166            strPtr->set((char*) opCode, size);
167            opCode += size;
168            SkDebugf(" string: %s", strPtr->c_str());
169            delete strPtr;
170            } break;
171        case SkScriptEngine2::kBoxToken: {
172            SkOperand2::OpType type;
173            memcpy(&type, opCode, sizeof(type));
174            opCode += sizeof(type);
175            size_t index = 0;
176            if (type == 0)
177                SkDebugf(" type: %s", gOperandNames[index].fName);
178            else {
179                while (type != 0) {
180                    SkASSERT(index + 1 < gOperandNamesSize);
181                    if (type & (1 << index)) {
182                        type = (SkOperand2::OpType) (type & ~(1 << index));
183                        SkDebugf(" type: %s", gOperandNames[index + 1].fName);
184                    }
185                    index++;
186                }
187            }
188            } break;
189        case SkScriptEngine2::kIfOp:
190        case SkScriptEngine2::kLogicalAndInt:
191        case SkScriptEngine2::kElseOp:
192        case SkScriptEngine2::kLogicalOrInt: {
193            int size;
194            memcpy(&size, opCode, sizeof(size));
195            opCode += sizeof(size);
196            SkDebugf(" offset (address): %d (%d)", size, opCode - start + size);
197            } break;
198        case SkScriptEngine2::kEnd:
199            goto done;
200        case SkScriptEngine2::kNop:
201                SkASSERT(0);
202        default:
203            break;
204    }
205    SkDebugf("\n");
206    } while (true);
207done:
208    SkDebugf("\n");
209}
210
211#endif
212