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#ifdef SK_CAN_USE_FLOAT
159            SkDebugf(" scalar: %g", SkScalarToFloat(scalar));
160#else
161            SkDebugf(" scalar: %x", scalar);
162#endif
163            } break;
164        case SkScriptEngine2::kStringAccumulator:
165        case SkScriptEngine2::kStringOperand: {
166            int size;
167            SkString* strPtr = new SkString();
168            memcpy(&size, opCode, sizeof(size));
169            opCode += sizeof(size);
170            strPtr->set((char*) opCode, size);
171            opCode += size;
172            SkDebugf(" string: %s", strPtr->c_str());
173            delete strPtr;
174            } break;
175        case SkScriptEngine2::kBoxToken: {
176            SkOperand2::OpType type;
177            memcpy(&type, opCode, sizeof(type));
178            opCode += sizeof(type);
179            size_t index = 0;
180            if (type == 0)
181                SkDebugf(" type: %s", gOperandNames[index].fName);
182            else {
183                while (type != 0) {
184                    SkASSERT(index + 1 < gOperandNamesSize);
185                    if (type & (1 << index)) {
186                        type = (SkOperand2::OpType) (type & ~(1 << index));
187                        SkDebugf(" type: %s", gOperandNames[index + 1].fName);
188                    }
189                    index++;
190                }
191            }
192            } break;
193        case SkScriptEngine2::kIfOp:
194        case SkScriptEngine2::kLogicalAndInt:
195        case SkScriptEngine2::kElseOp:
196        case SkScriptEngine2::kLogicalOrInt: {
197            int size;
198            memcpy(&size, opCode, sizeof(size));
199            opCode += sizeof(size);
200            SkDebugf(" offset (address): %d (%d)", size, opCode - start + size);
201            } break;
202        case SkScriptEngine2::kEnd:
203            goto done;
204        case SkScriptEngine2::kNop:
205                SkASSERT(0);
206        default:
207            break;
208    }
209    SkDebugf("\n");
210    } while (true);
211done:
212    SkDebugf("\n");
213}
214
215#endif
216