blob: 933e0d7c2b69f51234730fae4aa5b506bbb99e91 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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;
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000109 size_t index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000110 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 {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000127 SkASSERT((size_t)(opCode - start) < length);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++;
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000129 SkASSERT((size_t)op < gOpNamesSize);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 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);
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000179 size_t index = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180 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);
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000206 default:
207 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 }
209 SkDebugf("\n");
210 } while (true);
211done:
212 SkDebugf("\n");
213}
214
215#endif