Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_DEX_INSTRUCTION_H_
     18 #define ART_RUNTIME_DEX_INSTRUCTION_H_
     19 
     20 #include "base/logging.h"
     21 #include "base/macros.h"
     22 #include "globals.h"
     23 
     24 typedef uint8_t uint4_t;
     25 typedef int8_t int4_t;
     26 
     27 namespace art {
     28 
     29 class DexFile;
     30 
     31 enum {
     32   kNumPackedOpcodes = 0x100
     33 };
     34 
     35 class Instruction {
     36  public:
     37   // NOP-encoded switch-statement signatures.
     38   enum {
     39     kPackedSwitchSignature = 0x0100,
     40     kSparseSwitchSignature = 0x0200,
     41     kArrayDataSignature = 0x0300,
     42   };
     43 
     44   struct PACKED(4) PackedSwitchPayload {
     45     const uint16_t ident;
     46     const uint16_t case_count;
     47     const int32_t first_key;
     48     const int32_t targets[];
     49 
     50    private:
     51     DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
     52   };
     53 
     54   struct PACKED(4) SparseSwitchPayload {
     55     const uint16_t ident;
     56     const uint16_t case_count;
     57     const int32_t keys_and_targets[];
     58 
     59    public:
     60     const int32_t* GetKeys() const {
     61       return keys_and_targets;
     62     }
     63 
     64     const int32_t* GetTargets() const {
     65       return keys_and_targets + case_count;
     66     }
     67 
     68    private:
     69     DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
     70   };
     71 
     72   struct PACKED(4) ArrayDataPayload {
     73     const uint16_t ident;
     74     const uint16_t element_width;
     75     const uint32_t element_count;
     76     const uint8_t data[];
     77 
     78    private:
     79     DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
     80   };
     81 
     82   // TODO: the code layout below is deliberate to avoid this enum being picked up by
     83   //       generate-operator-out.py.
     84   enum Code
     85   {  // NOLINT(whitespace/braces)
     86 #define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
     87 #include "dex_instruction_list.h"
     88     DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
     89 #undef DEX_INSTRUCTION_LIST
     90 #undef INSTRUCTION_ENUM
     91   };
     92 
     93   enum Format {
     94     k10x,  // op
     95     k12x,  // op vA, vB
     96     k11n,  // op vA, #+B
     97     k11x,  // op vAA
     98     k10t,  // op +AA
     99     k20t,  // op +AAAA
    100     k22x,  // op vAA, vBBBB
    101     k21t,  // op vAA, +BBBB
    102     k21s,  // op vAA, #+BBBB
    103     k21h,  // op vAA, #+BBBB00000[00000000]
    104     k21c,  // op vAA, thing@BBBB
    105     k23x,  // op vAA, vBB, vCC
    106     k22b,  // op vAA, vBB, #+CC
    107     k22t,  // op vA, vB, +CCCC
    108     k22s,  // op vA, vB, #+CCCC
    109     k22c,  // op vA, vB, thing@CCCC
    110     k32x,  // op vAAAA, vBBBB
    111     k30t,  // op +AAAAAAAA
    112     k31t,  // op vAA, +BBBBBBBB
    113     k31i,  // op vAA, #+BBBBBBBB
    114     k31c,  // op vAA, thing@BBBBBBBB
    115     k35c,  // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
    116     k3rc,  // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
    117     k51l,  // op vAA, #+BBBBBBBBBBBBBBBB
    118   };
    119 
    120   enum Flags {
    121     kBranch   = 0x01,  // conditional or unconditional branch
    122     kContinue = 0x02,  // flow can continue to next statement
    123     kSwitch   = 0x04,  // switch statement
    124     kThrow    = 0x08,  // could cause an exception to be thrown
    125     kReturn   = 0x10,  // returns, no additional statements
    126     kInvoke   = 0x20,  // a flavor of invoke
    127     kUnconditional = 0x40,  // unconditional branch
    128   };
    129 
    130   enum VerifyFlag {
    131     kVerifyNone            = 0x00000,
    132     kVerifyRegA            = 0x00001,
    133     kVerifyRegAWide        = 0x00002,
    134     kVerifyRegB            = 0x00004,
    135     kVerifyRegBField       = 0x00008,
    136     kVerifyRegBMethod      = 0x00010,
    137     kVerifyRegBNewInstance = 0x00020,
    138     kVerifyRegBString      = 0x00040,
    139     kVerifyRegBType        = 0x00080,
    140     kVerifyRegBWide        = 0x00100,
    141     kVerifyRegC            = 0x00200,
    142     kVerifyRegCField       = 0x00400,
    143     kVerifyRegCNewArray    = 0x00800,
    144     kVerifyRegCType        = 0x01000,
    145     kVerifyRegCWide        = 0x02000,
    146     kVerifyArrayData       = 0x04000,
    147     kVerifyBranchTarget    = 0x08000,
    148     kVerifySwitchTargets   = 0x10000,
    149     kVerifyVarArg          = 0x20000,
    150     kVerifyVarArgRange     = 0x40000,
    151     kVerifyError           = 0x80000,
    152   };
    153 
    154   // Decodes this instruction, populating its arguments.
    155   void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
    156 
    157   // Returns the size (in 2 byte code units) of this instruction.
    158   size_t SizeInCodeUnits() const {
    159     int result = kInstructionSizeInCodeUnits[Opcode()];
    160     if (UNLIKELY(result < 0)) {
    161       return SizeInCodeUnitsComplexOpcode();
    162     } else {
    163       return static_cast<size_t>(result);
    164     }
    165   }
    166 
    167   // Reads an instruction out of the stream at the specified address.
    168   static const Instruction* At(const uint16_t* code) {
    169     DCHECK(code != NULL);
    170     return reinterpret_cast<const Instruction*>(code);
    171   }
    172 
    173   // Reads an instruction out of the stream from the current address plus an offset.
    174   const Instruction* RelativeAt(int32_t offset) const {
    175     return At(reinterpret_cast<const uint16_t*>(this) + offset);
    176   }
    177 
    178   // Returns a pointer to the next instruction in the stream.
    179   const Instruction* Next() const {
    180     return RelativeAt(SizeInCodeUnits());
    181   }
    182 
    183   // Returns a pointer to the instruction after this 1xx instruction in the stream.
    184   const Instruction* Next_1xx() const {
    185     DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
    186     return RelativeAt(1);
    187   }
    188 
    189   // Returns a pointer to the instruction after this 2xx instruction in the stream.
    190   const Instruction* Next_2xx() const {
    191     DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
    192     return RelativeAt(2);
    193   }
    194 
    195   // Returns a pointer to the instruction after this 3xx instruction in the stream.
    196   const Instruction* Next_3xx() const {
    197     DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
    198     return RelativeAt(3);
    199   }
    200 
    201   // Returns a pointer to the instruction after this 51l instruction in the stream.
    202   const Instruction* Next_51l() const {
    203     DCHECK(FormatOf(Opcode()) == k51l);
    204     return RelativeAt(5);
    205   }
    206 
    207   // Returns the name of this instruction's opcode.
    208   const char* Name() const {
    209     return Instruction::Name(Opcode());
    210   }
    211 
    212   // Returns the name of the given opcode.
    213   static const char* Name(Code opcode) {
    214     return kInstructionNames[opcode];
    215   }
    216 
    217   // VRegA
    218   bool HasVRegA() const;
    219   int32_t VRegA() const;
    220   int8_t VRegA_10t() const;
    221   uint8_t VRegA_10x() const;
    222   uint4_t VRegA_11n() const;
    223   uint8_t VRegA_11x() const;
    224   uint4_t VRegA_12x() const;
    225   int16_t VRegA_20t() const;
    226   uint8_t VRegA_21c() const;
    227   uint8_t VRegA_21h() const;
    228   uint8_t VRegA_21s() const;
    229   uint8_t VRegA_21t() const;
    230   uint8_t VRegA_22b() const;
    231   uint4_t VRegA_22c() const;
    232   uint4_t VRegA_22s() const;
    233   uint4_t VRegA_22t() const;
    234   uint8_t VRegA_22x() const;
    235   uint8_t VRegA_23x() const;
    236   int32_t VRegA_30t() const;
    237   uint8_t VRegA_31c() const;
    238   uint8_t VRegA_31i() const;
    239   uint8_t VRegA_31t() const;
    240   uint16_t VRegA_32x() const;
    241   uint4_t VRegA_35c() const;
    242   uint8_t VRegA_3rc() const;
    243   uint8_t VRegA_51l() const;
    244 
    245   // VRegB
    246   bool HasVRegB() const;
    247   int32_t VRegB() const;
    248   int4_t VRegB_11n() const;
    249   uint4_t VRegB_12x() const;
    250   uint16_t VRegB_21c() const;
    251   uint16_t VRegB_21h() const;
    252   int16_t VRegB_21s() const;
    253   int16_t VRegB_21t() const;
    254   uint8_t VRegB_22b() const;
    255   uint4_t VRegB_22c() const;
    256   uint4_t VRegB_22s() const;
    257   uint4_t VRegB_22t() const;
    258   uint16_t VRegB_22x() const;
    259   uint8_t VRegB_23x() const;
    260   uint32_t VRegB_31c() const;
    261   int32_t VRegB_31i() const;
    262   int32_t VRegB_31t() const;
    263   uint16_t VRegB_32x() const;
    264   uint16_t VRegB_35c() const;
    265   uint16_t VRegB_3rc() const;
    266   uint64_t VRegB_51l() const;  // vB_wide
    267 
    268   // VRegC
    269   bool HasVRegC() const;
    270   int32_t VRegC() const;
    271   int8_t VRegC_22b() const;
    272   uint16_t VRegC_22c() const;
    273   int16_t VRegC_22s() const;
    274   int16_t VRegC_22t() const;
    275   uint8_t VRegC_23x() const;
    276   uint4_t VRegC_35c() const;
    277   uint16_t VRegC_3rc() const;
    278 
    279   // Fills the given array with the 'arg' array of the instruction.
    280   void GetArgs(uint32_t args[5]) const;
    281 
    282   // Returns the opcode field of the instruction.
    283   Code Opcode() const {
    284     return static_cast<Code>(Fetch16(0) & 0xFF);
    285   }
    286 
    287   void SetOpcode(Code opcode) {
    288     DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
    289     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
    290     insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
    291   }
    292 
    293   void SetVRegA_10x(uint8_t val) {
    294     DCHECK(FormatOf(Opcode()) == k10x);
    295     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
    296     insns[0] = (val << 8) | (insns[0] & 0x00ff);
    297   }
    298 
    299   void SetVRegB_3rc(uint16_t val) {
    300     DCHECK(FormatOf(Opcode()) == k3rc);
    301     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
    302     insns[1] = val;
    303   }
    304 
    305   void SetVRegB_35c(uint16_t val) {
    306     DCHECK(FormatOf(Opcode()) == k35c);
    307     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
    308     insns[1] = val;
    309   }
    310 
    311   void SetVRegC_22c(uint16_t val) {
    312     DCHECK(FormatOf(Opcode()) == k22c);
    313     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
    314     insns[1] = val;
    315   }
    316 
    317   // Returns the format of the given opcode.
    318   static Format FormatOf(Code opcode) {
    319     return kInstructionFormats[opcode];
    320   }
    321 
    322   // Returns the flags for the given opcode.
    323   static int FlagsOf(Code opcode) {
    324     return kInstructionFlags[opcode];
    325   }
    326 
    327   // Returns true if this instruction is a branch.
    328   bool IsBranch() const {
    329     return (kInstructionFlags[Opcode()] & kBranch) != 0;
    330   }
    331 
    332   // Returns true if this instruction is a unconditional branch.
    333   bool IsUnconditional() const {
    334     return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
    335   }
    336 
    337   // Returns the branch offset if this instruction is a branch.
    338   int32_t GetTargetOffset() const;
    339 
    340   // Returns true if the instruction allows control flow to go to the following instruction.
    341   bool CanFlowThrough() const;
    342 
    343   // Returns true if this instruction is a switch.
    344   bool IsSwitch() const {
    345     return (kInstructionFlags[Opcode()] & kSwitch) != 0;
    346   }
    347 
    348   // Returns true if this instruction can throw.
    349   bool IsThrow() const {
    350     return (kInstructionFlags[Opcode()] & kThrow) != 0;
    351   }
    352 
    353   // Determine if the instruction is any of 'return' instructions.
    354   bool IsReturn() const {
    355     return (kInstructionFlags[Opcode()] & kReturn) != 0;
    356   }
    357 
    358   // Determine if this instruction ends execution of its basic block.
    359   bool IsBasicBlockEnd() const {
    360     return IsBranch() || IsReturn() || Opcode() == THROW;
    361   }
    362 
    363   // Determine if this instruction is an invoke.
    364   bool IsInvoke() const {
    365     return (kInstructionFlags[Opcode()] & kInvoke) != 0;
    366   }
    367 
    368   int GetVerifyTypeArgumentA() const {
    369     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
    370   }
    371 
    372   int GetVerifyTypeArgumentB() const {
    373     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
    374              kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
    375   }
    376 
    377   int GetVerifyTypeArgumentC() const {
    378     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
    379              kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
    380   }
    381 
    382   int GetVerifyExtraFlags() const {
    383     return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
    384              kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
    385   }
    386 
    387   // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
    388   uint32_t GetDexPc(const uint16_t* insns) const {
    389     return (reinterpret_cast<const uint16_t*>(this) - insns);
    390   }
    391 
    392   // Dump decoded version of instruction
    393   std::string DumpString(const DexFile*) const;
    394 
    395   // Dump code_units worth of this instruction, padding to code_units for shorter instructions
    396   std::string DumpHex(size_t code_units) const;
    397 
    398  private:
    399   size_t SizeInCodeUnitsComplexOpcode() const;
    400 
    401   uint16_t Fetch16(size_t offset) const {
    402     const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
    403     return insns[offset];
    404   }
    405 
    406   uint32_t Fetch32(size_t offset) const {
    407     return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
    408   }
    409 
    410   uint4_t InstA() const {
    411     return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f);
    412   }
    413 
    414   uint4_t InstB() const {
    415     return static_cast<uint4_t>(Fetch16(0) >> 12);
    416   }
    417 
    418   uint8_t InstAA() const {
    419     return static_cast<uint8_t>(Fetch16(0) >> 8);
    420   }
    421 
    422   static const char* const kInstructionNames[];
    423   static Format const kInstructionFormats[];
    424   static int const kInstructionFlags[];
    425   static int const kInstructionVerifyFlags[];
    426   static int const kInstructionSizeInCodeUnits[];
    427   DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
    428 };
    429 std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
    430 std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
    431 std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
    432 std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
    433 
    434 /*
    435  * Holds the contents of a decoded instruction.
    436  */
    437 struct DecodedInstruction {
    438   uint32_t vA;
    439   uint32_t vB;
    440   uint64_t vB_wide;        /* for k51l */
    441   uint32_t vC;
    442   uint32_t arg[5];         /* vC/D/E/F/G in invoke or filled-new-array */
    443   Instruction::Code opcode;
    444 
    445   explicit DecodedInstruction(const Instruction* inst) {
    446     inst->Decode(vA, vB, vB_wide, vC, arg);
    447     opcode = inst->Opcode();
    448   }
    449 };
    450 
    451 }  // namespace art
    452 
    453 #endif  // ART_RUNTIME_DEX_INSTRUCTION_H_
    454