• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GetKeysSparseSwitchPayload60     const int32_t* GetKeys() const {
61       return keys_and_targets;
62     }
63 
GetTargetsSparseSwitchPayload64     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.
SizeInCodeUnits()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.
At(const uint16_t * code)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.
RelativeAt(int32_t 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.
Next()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.
Next_1xx()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.
Next_2xx()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.
Next_3xx()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.
Next_51l()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.
Name()208   const char* Name() const {
209     return Instruction::Name(Opcode());
210   }
211 
212   // Returns the name of the given opcode.
Name(Code 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.
Opcode()283   Code Opcode() const {
284     return static_cast<Code>(Fetch16(0) & 0xFF);
285   }
286 
SetOpcode(Code opcode)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 
SetVRegA_10x(uint8_t val)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 
SetVRegB_3rc(uint16_t val)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 
SetVRegB_35c(uint16_t val)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 
SetVRegC_22c(uint16_t val)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.
FormatOf(Code opcode)318   static Format FormatOf(Code opcode) {
319     return kInstructionFormats[opcode];
320   }
321 
322   // Returns the flags for the given opcode.
FlagsOf(Code opcode)323   static int FlagsOf(Code opcode) {
324     return kInstructionFlags[opcode];
325   }
326 
327   // Returns true if this instruction is a branch.
IsBranch()328   bool IsBranch() const {
329     return (kInstructionFlags[Opcode()] & kBranch) != 0;
330   }
331 
332   // Returns true if this instruction is a unconditional branch.
IsUnconditional()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.
IsSwitch()344   bool IsSwitch() const {
345     return (kInstructionFlags[Opcode()] & kSwitch) != 0;
346   }
347 
348   // Returns true if this instruction can throw.
IsThrow()349   bool IsThrow() const {
350     return (kInstructionFlags[Opcode()] & kThrow) != 0;
351   }
352 
353   // Determine if the instruction is any of 'return' instructions.
IsReturn()354   bool IsReturn() const {
355     return (kInstructionFlags[Opcode()] & kReturn) != 0;
356   }
357 
358   // Determine if this instruction ends execution of its basic block.
IsBasicBlockEnd()359   bool IsBasicBlockEnd() const {
360     return IsBranch() || IsReturn() || Opcode() == THROW;
361   }
362 
363   // Determine if this instruction is an invoke.
IsInvoke()364   bool IsInvoke() const {
365     return (kInstructionFlags[Opcode()] & kInvoke) != 0;
366   }
367 
GetVerifyTypeArgumentA()368   int GetVerifyTypeArgumentA() const {
369     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
370   }
371 
GetVerifyTypeArgumentB()372   int GetVerifyTypeArgumentB() const {
373     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
374              kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
375   }
376 
GetVerifyTypeArgumentC()377   int GetVerifyTypeArgumentC() const {
378     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
379              kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
380   }
381 
GetVerifyExtraFlags()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.
GetDexPc(const uint16_t * 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 
Fetch16(size_t offset)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 
Fetch32(size_t offset)406   uint32_t Fetch32(size_t offset) const {
407     return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
408   }
409 
InstA()410   uint4_t InstA() const {
411     return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f);
412   }
413 
InstB()414   uint4_t InstB() const {
415     return static_cast<uint4_t>(Fetch16(0) >> 12);
416   }
417 
InstAA()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 
DecodedInstructionDecodedInstruction445   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