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 
16 static 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 
88 static size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]);
89 
90 #define OperandName(op) {SkOperand2::op, #op }
91 
92 static 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 
104 static size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]);
105 
106 // check to see that there are no missing or duplicate entries
ValidateDecompileTable()107 void 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 
decompile(const unsigned char * start,size_t length)123 void 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);
207 done:
208     SkDebugf("\n");
209 }
210 
211 #endif
212