• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
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 #include "SkScriptRuntime.h"
9 #include "SkScript2.h"
10 #include "SkMath.h"
11 #include "SkParse.h"
12 #include "SkScriptCallBack.h"
13 #include "SkString.h"
14 #include "SkOpArray.h"
15 
16 // script tokenizer
17 
18 // turn text into token string
19 // turn number literals into inline UTF8-style values
20 // process operators to turn standard notation into stack notation
21 
22 // defer processing until the tokens can all be resolved
23 // then, turn token strings into indices into the appropriate tables / dictionaries
24 
25 // consider: const evaluation?
26 
27 // replace script string with script tokens preceeded by special value
28 
29 // need second version of script plugins that return private index of found value?
30 	// then would need in script index of plugin, private index
31 
32 // encode brace stack push/pop as opcodes
33 
34 // should token script enocde type where possible?
35 
36 // current flow:
37 	// strip whitespace
38 	// if in array brace [ recurse, continue
39 	// if token, handle function, or array, or property (continue)
40 	// parse number, continue
41 	// parse token, continue
42 	// parse string literal, continue
43 	// if dot operator, handle dot, continue
44 	// if [ , handle array literal or accessor, continue
45 	// if ), pop (if function, break)
46 	// if ], pop ; if ',' break
47 	// handle logical ops
48 	// or, handle arithmetic ops
49 	// loop
50 
51 // !!! things to do
52 	// add separate processing loop to advance while suppressed
53 	// or, include jump offset to skip suppressed code?
54 
~SkScriptRuntime()55 SkScriptRuntime::~SkScriptRuntime() {
56 	for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++)
57 		delete *stringPtr;
58 	for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++)
59 		delete *arrayPtr;
60 }
61 
executeTokens(unsigned char * opCode)62 bool SkScriptRuntime::executeTokens(unsigned char* opCode) {
63 	SkOperand2 operand[2];	// 1=accumulator and 2=operand
64 	SkScriptEngine2::TypeOp op;
65 	size_t ref;
66 	int index, size;
67 	int registerLoad;
68 	SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING;
69 	do {
70 	switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) {
71 		case SkScriptEngine2::kArrayToken:	// create an array
72 			operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/);
73 			break;
74 		case SkScriptEngine2::kArrayIndex:	// array accessor
75 			index = operand[1].fS32;
76 			if (index >= operand[0].fArray->count()) {
77 				fError = kArrayIndexOutOfBounds;
78 				return false;
79 			}
80 			operand[0] = operand[0].fArray->begin()[index];
81 			break;
82 		case SkScriptEngine2::kArrayParam:	// array initializer, or function param
83 			*operand[0].fArray->append() = operand[1];
84 			break;
85 		case SkScriptEngine2::kCallback:
86 			memcpy(&index, opCode, sizeof(index));
87 			opCode += sizeof(index);
88 			callBack = fCallBackArray[index];
89 			break;
90 		case SkScriptEngine2::kFunctionCall: {
91 			memcpy(&ref, opCode, sizeof(ref));
92 			opCode += sizeof(ref);
93 			SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack;
94 			if (callBackFunction->invoke(ref, operand[0].fArray, /* params */
95 					&operand[0] /* result */) == false) {
96 				fError = kFunctionCallFailed;
97 				return false;
98 			}
99 			} break;
100 		case SkScriptEngine2::kMemberOp: {
101 			memcpy(&ref, opCode, sizeof(ref));
102 			opCode += sizeof(ref);
103 			SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack;
104 			if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) {
105 				fError = kMemberOpFailed;
106 				return false;
107 			}
108 			} break;
109 		case SkScriptEngine2::kPropertyOp: {
110 			memcpy(&ref, opCode, sizeof(ref));
111 			opCode += sizeof(ref);
112 			SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack;
113 			if (callBackProperty->getResult(ref, &operand[0])== false) {
114 				fError = kPropertyOpFailed;
115 				return false;
116 			}
117 			} break;
118 		case SkScriptEngine2::kAccumulatorPop:
119 			fRunStack.pop(&operand[0]);
120 			break;
121 		case SkScriptEngine2::kAccumulatorPush:
122 			*fRunStack.push() = operand[0];
123 			break;
124 		case SkScriptEngine2::kIntegerAccumulator:
125 		case SkScriptEngine2::kIntegerOperand:
126 			registerLoad = op - SkScriptEngine2::kIntegerAccumulator;
127 			memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t));
128 			opCode += sizeof(int32_t);
129 			break;
130 		case SkScriptEngine2::kScalarAccumulator:
131 		case SkScriptEngine2::kScalarOperand:
132 			registerLoad = op - SkScriptEngine2::kScalarAccumulator;
133 			memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar));
134 			opCode += sizeof(SkScalar);
135 			break;
136 		case SkScriptEngine2::kStringAccumulator:
137 		case SkScriptEngine2::kStringOperand: {
138 			SkString* strPtr = new SkString();
139 			track(strPtr);
140 			registerLoad = op - SkScriptEngine2::kStringAccumulator;
141 			memcpy(&size, opCode, sizeof(size));
142 			opCode += sizeof(size);
143 			strPtr->set((char*) opCode, size);
144 			opCode += size;
145 			operand[registerLoad].fString = strPtr;
146 			} break;
147 		case SkScriptEngine2::kStringTrack: // call after kObjectToValue
148 			track(operand[0].fString);
149 			break;
150 		case SkScriptEngine2::kBoxToken: {
151 			SkOperand2::OpType type;
152 			memcpy(&type, opCode, sizeof(type));
153 			opCode += sizeof(type);
154 			SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack;
155 			if (callBackBox->convert(type, &operand[0]) == false)
156 				return false;
157 			} break;
158 		case SkScriptEngine2::kUnboxToken:
159 		case SkScriptEngine2::kUnboxToken2: {
160 			SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack;
161 			if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false)
162 				return false;
163 			} break;
164 		case SkScriptEngine2::kIfOp:
165 		case SkScriptEngine2::kLogicalAndInt:
166 			memcpy(&size, opCode, sizeof(size));
167 			opCode += sizeof(size);
168 			if (operand[0].fS32 == 0)
169 				opCode += size; // skip to else (or end of if predicate)
170 			break;
171 		case SkScriptEngine2::kElseOp:
172 			memcpy(&size, opCode, sizeof(size));
173 			opCode += sizeof(size);
174 			opCode += size; // if true: after predicate, always skip to end of else
175 			break;
176 		case SkScriptEngine2::kLogicalOrInt:
177 			memcpy(&size, opCode, sizeof(size));
178 			opCode += sizeof(size);
179 			if (operand[0].fS32 != 0)
180 				opCode += size; // skip to kToBool opcode after || predicate
181 			break;
182 		// arithmetic conversion ops
183 		case SkScriptEngine2::kFlipOpsOp:
184 			SkTSwap(operand[0], operand[1]);
185 			break;
186 		case SkScriptEngine2::kIntToString:
187 		case SkScriptEngine2::kIntToString2:
188 		case SkScriptEngine2::kScalarToString:
189 		case SkScriptEngine2::kScalarToString2:{
190 			SkString* strPtr = new SkString();
191 			track(strPtr);
192 			if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2)
193 				strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32);
194 			else
195 				strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar);
196 			operand[0].fString = strPtr;
197 			} break;
198 		case SkScriptEngine2::kIntToScalar:
199 		case SkScriptEngine2::kIntToScalar2:
200 			operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32);
201 			break;
202 		case SkScriptEngine2::kStringToInt:
203 			if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == false)
204 				return false;
205 			break;
206 		case SkScriptEngine2::kStringToScalar:
207 		case SkScriptEngine2::kStringToScalar2:
208 			if (SkParse::FindScalar(operand[0].fString->c_str(),
209 					&operand[op - SkScriptEngine2::kStringToScalar].fScalar) == false)
210 				return false;
211 			break;
212 		case SkScriptEngine2::kScalarToInt:
213 			operand[0].fS32 = SkScalarFloor(operand[0].fScalar);
214 			break;
215 		// arithmetic ops
216 		case SkScriptEngine2::kAddInt:
217 			operand[0].fS32 += operand[1].fS32;
218 			break;
219 		case SkScriptEngine2::kAddScalar:
220 			operand[0].fScalar += operand[1].fScalar;
221 			break;
222 		case SkScriptEngine2::kAddString:
223 //			if (fTrackString.find(operand[1].fString) < 0) {
224 //				operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString));
225 //				track(operand[1].fString);
226 //			}
227 			operand[0].fString->append(*operand[1].fString);
228 			break;
229 		case SkScriptEngine2::kBitAndInt:
230 			operand[0].fS32 &= operand[1].fS32;
231 			break;
232 		case SkScriptEngine2::kBitNotInt:
233 			operand[0].fS32 = ~operand[0].fS32;
234 			break;
235 		case SkScriptEngine2::kBitOrInt:
236 			operand[0].fS32 |= operand[1].fS32;
237 			break;
238 		case SkScriptEngine2::kDivideInt:
239 			SkASSERT(operand[1].fS32 != 0);
240 			if (operand[1].fS32 == 0)
241 				operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 :
242 					operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32;
243 			else
244 			if (operand[1].fS32 != 0) // throw error on divide by zero?
245 				operand[0].fS32 /= operand[1].fS32;
246 			break;
247 		case SkScriptEngine2::kDivideScalar:
248 			if (operand[1].fScalar == 0)
249 				operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN :
250 					operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax;
251 			else
252 				operand[0].fScalar = SkScalarDiv(operand[0].fScalar, operand[1].fScalar);
253 			break;
254 		case SkScriptEngine2::kEqualInt:
255 			operand[0].fS32 = operand[0].fS32 == operand[1].fS32;
256 			break;
257 		case SkScriptEngine2::kEqualScalar:
258 			operand[0].fS32 = operand[0].fScalar == operand[1].fScalar;
259 			break;
260 		case SkScriptEngine2::kEqualString:
261 			operand[0].fS32 = *operand[0].fString == *operand[1].fString;
262 			break;
263 		case SkScriptEngine2::kGreaterEqualInt:
264 			operand[0].fS32 = operand[0].fS32 >= operand[1].fS32;
265 			break;
266 		case SkScriptEngine2::kGreaterEqualScalar:
267 			operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar;
268 			break;
269 		case SkScriptEngine2::kGreaterEqualString:
270 			operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0;
271 			break;
272 		case SkScriptEngine2::kToBool:
273 			operand[0].fS32 = !! operand[0].fS32;
274 			break;
275 		case SkScriptEngine2::kLogicalNotInt:
276 			operand[0].fS32 = ! operand[0].fS32;
277 			break;
278 		case SkScriptEngine2::kMinusInt:
279 			operand[0].fS32 = -operand[0].fS32;
280 			break;
281 		case SkScriptEngine2::kMinusScalar:
282 			operand[0].fScalar = -operand[0].fScalar;
283 			break;
284 		case SkScriptEngine2::kModuloInt:
285 			operand[0].fS32 %= operand[1].fS32;
286 			break;
287 		case SkScriptEngine2::kModuloScalar:
288 			operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar);
289 			break;
290 		case SkScriptEngine2::kMultiplyInt:
291 			operand[0].fS32 *= operand[1].fS32;
292 			break;
293 		case SkScriptEngine2::kMultiplyScalar:
294 			operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar);
295 			break;
296 		case SkScriptEngine2::kShiftLeftInt:
297 			operand[0].fS32 <<= operand[1].fS32;
298 			break;
299 		case SkScriptEngine2::kShiftRightInt:
300 			operand[0].fS32 >>= operand[1].fS32;
301 			break;
302 		case SkScriptEngine2::kSubtractInt:
303 			operand[0].fS32 -= operand[1].fS32;
304 			break;
305 		case SkScriptEngine2::kSubtractScalar:
306 			operand[0].fScalar -= operand[1].fScalar;
307 			break;
308 		case SkScriptEngine2::kXorInt:
309 			operand[0].fS32 ^= operand[1].fS32;
310 			break;
311 		case SkScriptEngine2::kEnd:
312 			goto done;
313 		case SkScriptEngine2::kNop:
314 				SkASSERT(0);
315     default:
316         break;
317 	}
318 	} while (true);
319 done:
320 	fRunStack.push(operand[0]);
321 	return true;
322 }
323 
getResult(SkOperand2 * result)324 bool SkScriptRuntime::getResult(SkOperand2* result) {
325 	if (fRunStack.count() == 0)
326 		return false;
327 	fRunStack.pop(result);
328 	return true;
329 }
330 
track(SkOpArray * array)331 void SkScriptRuntime::track(SkOpArray* array) {
332 	SkASSERT(fTrackArray.find(array) < 0);
333 	*fTrackArray.append() = array;
334 }
335 
track(SkString * string)336 void SkScriptRuntime::track(SkString* string) {
337 	SkASSERT(fTrackString.find(string) < 0);
338 	*fTrackString.append() = string;
339 }
340 
untrack(SkOpArray * array)341 void SkScriptRuntime::untrack(SkOpArray* array) {
342 	int index = fTrackArray.find(array);
343 	SkASSERT(index >= 0);
344 	fTrackArray.begin()[index] = NULL;
345 }
346 
untrack(SkString * string)347 void SkScriptRuntime::untrack(SkString* string) {
348 	int index = fTrackString.find(string);
349 	SkASSERT(index >= 0);
350 	fTrackString.begin()[index] = NULL;
351 }
352 
353