|
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 |
|
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 |
|
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 |