Home | History | Annotate | Download | only in animator
      1 /* libs/graphics/animator/SkScriptDecompile.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkScript2.h"
     19 
     20 #ifdef SK_DEBUG
     21 
     22 #define TypeOpName(op) {SkScriptEngine2::op, #op }
     23 
     24 static const struct OpName {
     25     SkScriptEngine2::TypeOp fOp;
     26     const char* fName;
     27 } gOpNames[] = {
     28     TypeOpName(kNop), // should never get generated
     29     TypeOpName(kAccumulatorPop),
     30     TypeOpName(kAccumulatorPush),
     31     TypeOpName(kAddInt),
     32     TypeOpName(kAddScalar),
     33     TypeOpName(kAddString), // string concat
     34     TypeOpName(kArrayIndex),
     35     TypeOpName(kArrayParam),
     36     TypeOpName(kArrayToken),
     37     TypeOpName(kBitAndInt),
     38     TypeOpName(kBitNotInt),
     39     TypeOpName(kBitOrInt),
     40     TypeOpName(kBoxToken),
     41     TypeOpName(kCallback),
     42     TypeOpName(kDivideInt),
     43     TypeOpName(kDivideScalar),
     44     TypeOpName(kDotOperator),
     45     TypeOpName(kElseOp),
     46     TypeOpName(kEnd),
     47     TypeOpName(kEqualInt),
     48     TypeOpName(kEqualScalar),
     49     TypeOpName(kEqualString),
     50     TypeOpName(kFunctionCall),
     51     TypeOpName(kFlipOpsOp),
     52     TypeOpName(kFunctionToken),
     53     TypeOpName(kGreaterEqualInt),
     54     TypeOpName(kGreaterEqualScalar),
     55     TypeOpName(kGreaterEqualString),
     56     TypeOpName(kIfOp),
     57     TypeOpName(kIntToScalar),
     58     TypeOpName(kIntToScalar2),
     59     TypeOpName(kIntToString),
     60     TypeOpName(kIntToString2),
     61     TypeOpName(kIntegerAccumulator),
     62     TypeOpName(kIntegerOperand),
     63     TypeOpName(kLogicalAndInt),
     64     TypeOpName(kLogicalNotInt),
     65     TypeOpName(kLogicalOrInt),
     66     TypeOpName(kMemberOp),
     67     TypeOpName(kMinusInt),
     68     TypeOpName(kMinusScalar),
     69     TypeOpName(kModuloInt),
     70     TypeOpName(kModuloScalar),
     71     TypeOpName(kMultiplyInt),
     72     TypeOpName(kMultiplyScalar),
     73     TypeOpName(kPropertyOp),
     74     TypeOpName(kScalarAccumulator),
     75     TypeOpName(kScalarOperand),
     76     TypeOpName(kScalarToInt),
     77     TypeOpName(kScalarToInt2),
     78     TypeOpName(kScalarToString),
     79     TypeOpName(kScalarToString2),
     80     TypeOpName(kShiftLeftInt),
     81     TypeOpName(kShiftRightInt), // signed
     82     TypeOpName(kStringAccumulator),
     83     TypeOpName(kStringOperand),
     84     TypeOpName(kStringToInt),
     85     TypeOpName(kStringToScalar),
     86     TypeOpName(kStringToScalar2),
     87     TypeOpName(kStringTrack),
     88     TypeOpName(kSubtractInt),
     89     TypeOpName(kSubtractScalar),
     90     TypeOpName(kToBool),
     91     TypeOpName(kUnboxToken),
     92     TypeOpName(kUnboxToken2),
     93     TypeOpName(kXorInt)
     94 };
     95 
     96 static size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]);
     97 
     98 #define OperandName(op) {SkOperand2::op, #op }
     99 
    100 static const struct OperName {
    101     SkOperand2::OpType fType;
    102     const char* fName;
    103 } gOperandNames[] = {
    104     OperandName(kNoType),
    105     OperandName(kS32),
    106     OperandName(kScalar),
    107     OperandName(kString),
    108     OperandName(kArray),
    109     OperandName(kObject)
    110 };
    111 
    112 static size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]);
    113 
    114 // check to see that there are no missing or duplicate entries
    115 void SkScriptEngine2::ValidateDecompileTable() {
    116     SkScriptEngine2::TypeOp op = SkScriptEngine2::kNop;
    117     size_t index;
    118     for (index = 0; index < gOpNamesSize; index++) {
    119         SkASSERT(gOpNames[index].fOp == op);
    120         op = (SkScriptEngine2::TypeOp) (op + 1);
    121     }
    122     index = 0;
    123     SkOperand2::OpType type = SkOperand2::kNoType;
    124     SkASSERT(gOperandNames[index].fType == type);
    125     for (; index < gOperandNamesSize - 1; ) {
    126         type = (SkOperand2::OpType) (1 << index);
    127         SkASSERT(gOperandNames[++index].fType == type);
    128     }
    129 }
    130 
    131 void SkScriptEngine2::decompile(const unsigned char* start, size_t length) {
    132     SkASSERT(length > 0);
    133     const unsigned char* opCode = start;
    134     do {
    135         SkASSERT((size_t)(opCode - start) < length);
    136         SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++;
    137         SkASSERT((size_t)op < gOpNamesSize);
    138         SkDebugf("%d: %s", opCode - start - 1, gOpNames[op].fName);
    139         switch (op) {
    140         case SkScriptEngine2::kCallback: {
    141             int index;
    142             memcpy(&index, opCode, sizeof(index));
    143             opCode += sizeof(index);
    144             SkDebugf(" index: %d", index);
    145             } break;
    146         case SkScriptEngine2::kFunctionCall:
    147         case SkScriptEngine2::kMemberOp:
    148         case SkScriptEngine2::kPropertyOp: {
    149             size_t ref;
    150             memcpy(&ref, opCode, sizeof(ref));
    151             opCode += sizeof(ref);
    152             SkDebugf(" ref: %d", ref);
    153             } break;
    154         case SkScriptEngine2::kIntegerAccumulator:
    155         case SkScriptEngine2::kIntegerOperand: {
    156             int32_t integer;
    157             memcpy(&integer, opCode, sizeof(integer));
    158             opCode += sizeof(int32_t);
    159             SkDebugf(" integer: %d", integer);
    160             } break;
    161         case SkScriptEngine2::kScalarAccumulator:
    162         case SkScriptEngine2::kScalarOperand: {
    163             SkScalar scalar;
    164             memcpy(&scalar, opCode, sizeof(scalar));
    165             opCode += sizeof(SkScalar);
    166 #ifdef SK_CAN_USE_FLOAT
    167             SkDebugf(" scalar: %g", SkScalarToFloat(scalar));
    168 #else
    169             SkDebugf(" scalar: %x", scalar);
    170 #endif
    171             } break;
    172         case SkScriptEngine2::kStringAccumulator:
    173         case SkScriptEngine2::kStringOperand: {
    174             int size;
    175             SkString* strPtr = new SkString();
    176             memcpy(&size, opCode, sizeof(size));
    177             opCode += sizeof(size);
    178             strPtr->set((char*) opCode, size);
    179             opCode += size;
    180             SkDebugf(" string: %s", strPtr->c_str());
    181             delete strPtr;
    182             } break;
    183         case SkScriptEngine2::kBoxToken: {
    184             SkOperand2::OpType type;
    185             memcpy(&type, opCode, sizeof(type));
    186             opCode += sizeof(type);
    187             size_t index = 0;
    188             if (type == 0)
    189                 SkDebugf(" type: %s", gOperandNames[index].fName);
    190             else {
    191                 while (type != 0) {
    192                     SkASSERT(index + 1 < gOperandNamesSize);
    193                     if (type & (1 << index)) {
    194                         type = (SkOperand2::OpType) (type & ~(1 << index));
    195                         SkDebugf(" type: %s", gOperandNames[index + 1].fName);
    196                     }
    197                     index++;
    198                 }
    199             }
    200             } break;
    201         case SkScriptEngine2::kIfOp:
    202         case SkScriptEngine2::kLogicalAndInt:
    203         case SkScriptEngine2::kElseOp:
    204         case SkScriptEngine2::kLogicalOrInt: {
    205             int size;
    206             memcpy(&size, opCode, sizeof(size));
    207             opCode += sizeof(size);
    208             SkDebugf(" offset (address): %d (%d)", size, opCode - start + size);
    209             } break;
    210         case SkScriptEngine2::kEnd:
    211             goto done;
    212         case SkScriptEngine2::kNop:
    213                 SkASSERT(0);
    214         default:
    215             break;
    216     }
    217     SkDebugf("\n");
    218     } while (true);
    219 done:
    220     SkDebugf("\n");
    221 }
    222 
    223 #endif
    224