michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkScript2.h" michael@0: michael@0: #ifdef SK_DEBUG michael@0: michael@0: #define TypeOpName(op) {SkScriptEngine2::op, #op } michael@0: michael@0: static const struct OpName { michael@0: SkScriptEngine2::TypeOp fOp; michael@0: const char* fName; michael@0: } gOpNames[] = { michael@0: TypeOpName(kNop), // should never get generated michael@0: TypeOpName(kAccumulatorPop), michael@0: TypeOpName(kAccumulatorPush), michael@0: TypeOpName(kAddInt), michael@0: TypeOpName(kAddScalar), michael@0: TypeOpName(kAddString), // string concat michael@0: TypeOpName(kArrayIndex), michael@0: TypeOpName(kArrayParam), michael@0: TypeOpName(kArrayToken), michael@0: TypeOpName(kBitAndInt), michael@0: TypeOpName(kBitNotInt), michael@0: TypeOpName(kBitOrInt), michael@0: TypeOpName(kBoxToken), michael@0: TypeOpName(kCallback), michael@0: TypeOpName(kDivideInt), michael@0: TypeOpName(kDivideScalar), michael@0: TypeOpName(kDotOperator), michael@0: TypeOpName(kElseOp), michael@0: TypeOpName(kEnd), michael@0: TypeOpName(kEqualInt), michael@0: TypeOpName(kEqualScalar), michael@0: TypeOpName(kEqualString), michael@0: TypeOpName(kFunctionCall), michael@0: TypeOpName(kFlipOpsOp), michael@0: TypeOpName(kFunctionToken), michael@0: TypeOpName(kGreaterEqualInt), michael@0: TypeOpName(kGreaterEqualScalar), michael@0: TypeOpName(kGreaterEqualString), michael@0: TypeOpName(kIfOp), michael@0: TypeOpName(kIntToScalar), michael@0: TypeOpName(kIntToScalar2), michael@0: TypeOpName(kIntToString), michael@0: TypeOpName(kIntToString2), michael@0: TypeOpName(kIntegerAccumulator), michael@0: TypeOpName(kIntegerOperand), michael@0: TypeOpName(kLogicalAndInt), michael@0: TypeOpName(kLogicalNotInt), michael@0: TypeOpName(kLogicalOrInt), michael@0: TypeOpName(kMemberOp), michael@0: TypeOpName(kMinusInt), michael@0: TypeOpName(kMinusScalar), michael@0: TypeOpName(kModuloInt), michael@0: TypeOpName(kModuloScalar), michael@0: TypeOpName(kMultiplyInt), michael@0: TypeOpName(kMultiplyScalar), michael@0: TypeOpName(kPropertyOp), michael@0: TypeOpName(kScalarAccumulator), michael@0: TypeOpName(kScalarOperand), michael@0: TypeOpName(kScalarToInt), michael@0: TypeOpName(kScalarToInt2), michael@0: TypeOpName(kScalarToString), michael@0: TypeOpName(kScalarToString2), michael@0: TypeOpName(kShiftLeftInt), michael@0: TypeOpName(kShiftRightInt), // signed michael@0: TypeOpName(kStringAccumulator), michael@0: TypeOpName(kStringOperand), michael@0: TypeOpName(kStringToInt), michael@0: TypeOpName(kStringToScalar), michael@0: TypeOpName(kStringToScalar2), michael@0: TypeOpName(kStringTrack), michael@0: TypeOpName(kSubtractInt), michael@0: TypeOpName(kSubtractScalar), michael@0: TypeOpName(kToBool), michael@0: TypeOpName(kUnboxToken), michael@0: TypeOpName(kUnboxToken2), michael@0: TypeOpName(kXorInt) michael@0: }; michael@0: michael@0: static size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]); michael@0: michael@0: #define OperandName(op) {SkOperand2::op, #op } michael@0: michael@0: static const struct OperName { michael@0: SkOperand2::OpType fType; michael@0: const char* fName; michael@0: } gOperandNames[] = { michael@0: OperandName(kNoType), michael@0: OperandName(kS32), michael@0: OperandName(kScalar), michael@0: OperandName(kString), michael@0: OperandName(kArray), michael@0: OperandName(kObject) michael@0: }; michael@0: michael@0: static size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]); michael@0: michael@0: // check to see that there are no missing or duplicate entries michael@0: void SkScriptEngine2::ValidateDecompileTable() { michael@0: SkScriptEngine2::TypeOp op = SkScriptEngine2::kNop; michael@0: size_t index; michael@0: for (index = 0; index < gOpNamesSize; index++) { michael@0: SkASSERT(gOpNames[index].fOp == op); michael@0: op = (SkScriptEngine2::TypeOp) (op + 1); michael@0: } michael@0: index = 0; michael@0: SkOperand2::OpType type = SkOperand2::kNoType; michael@0: SkASSERT(gOperandNames[index].fType == type); michael@0: for (; index < gOperandNamesSize - 1; ) { michael@0: type = (SkOperand2::OpType) (1 << index); michael@0: SkASSERT(gOperandNames[++index].fType == type); michael@0: } michael@0: } michael@0: michael@0: void SkScriptEngine2::decompile(const unsigned char* start, size_t length) { michael@0: SkASSERT(length > 0); michael@0: const unsigned char* opCode = start; michael@0: do { michael@0: SkASSERT((size_t)(opCode - start) < length); michael@0: SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++; michael@0: SkASSERT((size_t)op < gOpNamesSize); michael@0: SkDebugf("%d: %s", opCode - start - 1, gOpNames[op].fName); michael@0: switch (op) { michael@0: case SkScriptEngine2::kCallback: { michael@0: int index; michael@0: memcpy(&index, opCode, sizeof(index)); michael@0: opCode += sizeof(index); michael@0: SkDebugf(" index: %d", index); michael@0: } break; michael@0: case SkScriptEngine2::kFunctionCall: michael@0: case SkScriptEngine2::kMemberOp: michael@0: case SkScriptEngine2::kPropertyOp: { michael@0: size_t ref; michael@0: memcpy(&ref, opCode, sizeof(ref)); michael@0: opCode += sizeof(ref); michael@0: SkDebugf(" ref: %d", ref); michael@0: } break; michael@0: case SkScriptEngine2::kIntegerAccumulator: michael@0: case SkScriptEngine2::kIntegerOperand: { michael@0: int32_t integer; michael@0: memcpy(&integer, opCode, sizeof(integer)); michael@0: opCode += sizeof(int32_t); michael@0: SkDebugf(" integer: %d", integer); michael@0: } break; michael@0: case SkScriptEngine2::kScalarAccumulator: michael@0: case SkScriptEngine2::kScalarOperand: { michael@0: SkScalar scalar; michael@0: memcpy(&scalar, opCode, sizeof(scalar)); michael@0: opCode += sizeof(SkScalar); michael@0: SkDebugf(" scalar: %g", SkScalarToFloat(scalar)); michael@0: } break; michael@0: case SkScriptEngine2::kStringAccumulator: michael@0: case SkScriptEngine2::kStringOperand: { michael@0: int size; michael@0: SkString* strPtr = new SkString(); michael@0: memcpy(&size, opCode, sizeof(size)); michael@0: opCode += sizeof(size); michael@0: strPtr->set((char*) opCode, size); michael@0: opCode += size; michael@0: SkDebugf(" string: %s", strPtr->c_str()); michael@0: delete strPtr; michael@0: } break; michael@0: case SkScriptEngine2::kBoxToken: { michael@0: SkOperand2::OpType type; michael@0: memcpy(&type, opCode, sizeof(type)); michael@0: opCode += sizeof(type); michael@0: size_t index = 0; michael@0: if (type == 0) michael@0: SkDebugf(" type: %s", gOperandNames[index].fName); michael@0: else { michael@0: while (type != 0) { michael@0: SkASSERT(index + 1 < gOperandNamesSize); michael@0: if (type & (1 << index)) { michael@0: type = (SkOperand2::OpType) (type & ~(1 << index)); michael@0: SkDebugf(" type: %s", gOperandNames[index + 1].fName); michael@0: } michael@0: index++; michael@0: } michael@0: } michael@0: } break; michael@0: case SkScriptEngine2::kIfOp: michael@0: case SkScriptEngine2::kLogicalAndInt: michael@0: case SkScriptEngine2::kElseOp: michael@0: case SkScriptEngine2::kLogicalOrInt: { michael@0: int size; michael@0: memcpy(&size, opCode, sizeof(size)); michael@0: opCode += sizeof(size); michael@0: SkDebugf(" offset (address): %d (%d)", size, opCode - start + size); michael@0: } break; michael@0: case SkScriptEngine2::kEnd: michael@0: goto done; michael@0: case SkScriptEngine2::kNop: michael@0: SkASSERT(0); michael@0: default: michael@0: break; michael@0: } michael@0: SkDebugf("\n"); michael@0: } while (true); michael@0: done: michael@0: SkDebugf("\n"); michael@0: } michael@0: michael@0: #endif