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