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 #include "dex_instruction-inl.h"
     18 
     19 #include "dex_file-inl.h"
     20 #include "utils.h"
     21 #include <iomanip>
     22 
     23 namespace art {
     24 
     25 const char* const Instruction::kInstructionNames[] = {
     26 #define INSTRUCTION_NAME(o, c, pname, f, r, i, a, v) pname,
     27 #include "dex_instruction_list.h"
     28   DEX_INSTRUCTION_LIST(INSTRUCTION_NAME)
     29 #undef DEX_INSTRUCTION_LIST
     30 #undef INSTRUCTION_NAME
     31 };
     32 
     33 Instruction::Format const Instruction::kInstructionFormats[] = {
     34 #define INSTRUCTION_FORMAT(o, c, p, format, r, i, a, v) format,
     35 #include "dex_instruction_list.h"
     36   DEX_INSTRUCTION_LIST(INSTRUCTION_FORMAT)
     37 #undef DEX_INSTRUCTION_LIST
     38 #undef INSTRUCTION_FORMAT
     39 };
     40 
     41 int const Instruction::kInstructionFlags[] = {
     42 #define INSTRUCTION_FLAGS(o, c, p, f, r, i, flags, v) flags,
     43 #include "dex_instruction_list.h"
     44   DEX_INSTRUCTION_LIST(INSTRUCTION_FLAGS)
     45 #undef DEX_INSTRUCTION_LIST
     46 #undef INSTRUCTION_FLAGS
     47 };
     48 
     49 int const Instruction::kInstructionVerifyFlags[] = {
     50 #define INSTRUCTION_VERIFY_FLAGS(o, c, p, f, r, i, a, vflags) vflags,
     51 #include "dex_instruction_list.h"
     52   DEX_INSTRUCTION_LIST(INSTRUCTION_VERIFY_FLAGS)
     53 #undef DEX_INSTRUCTION_LIST
     54 #undef INSTRUCTION_VERIFY_FLAGS
     55 };
     56 
     57 int const Instruction::kInstructionSizeInCodeUnits[] = {
     58 #define INSTRUCTION_SIZE(opcode, c, p, format, r, i, a, v) \
     59     ((opcode == NOP)                        ? -1 : \
     60      ((format >= k10x) && (format <= k10t)) ?  1 : \
     61      ((format >= k20t) && (format <= k22c)) ?  2 : \
     62      ((format >= k32x) && (format <= k3rc)) ?  3 : \
     63       (format == k51l)                      ?  5 : -1),
     64 #include "dex_instruction_list.h"
     65   DEX_INSTRUCTION_LIST(INSTRUCTION_SIZE)
     66 #undef DEX_INSTRUCTION_LIST
     67 #undef INSTRUCTION_SIZE
     68 };
     69 
     70 /*
     71  * Handy macros for helping decode instructions.
     72  */
     73 #define FETCH(_offset)      (insns[(_offset)])
     74 #define FETCH_uint32(_offset)   (fetch_uint32_impl((_offset), insns))
     75 #define INST_A(_insn)       (((uint16_t)(_insn) >> 8) & 0x0f)
     76 #define INST_B(_insn)       ((uint16_t)(_insn) >> 12)
     77 #define INST_AA(_insn)      ((_insn) >> 8)
     78 
     79 /* Helper for FETCH_uint32, above. */
     80 static inline uint32_t fetch_uint32_impl(uint32_t offset, const uint16_t* insns) {
     81   return insns[offset] | ((uint32_t) insns[offset+1] << 16);
     82 }
     83 
     84 
     85 bool Instruction::HasVRegC() const {
     86   switch (FormatOf(Opcode())) {
     87     case k23x: return true;
     88     case k35c: return true;
     89     case k3rc: return true;
     90     default: return false;
     91   }
     92 }
     93 
     94 bool Instruction::HasVRegB() const {
     95   switch (FormatOf(Opcode())) {
     96     case k12x: return true;
     97     case k22b: return true;
     98     case k22c: return true;
     99     case k22s: return true;
    100     case k22t: return true;
    101     case k22x: return true;
    102     case k23x: return true;
    103     case k32x: return true;
    104     default: return false;
    105   }
    106 }
    107 
    108 bool Instruction::HasVRegA() const {
    109   switch (FormatOf(Opcode())) {
    110     case k11n: return true;
    111     case k11x: return true;
    112     case k12x: return true;
    113     case k21c: return true;
    114     case k21h: return true;
    115     case k21s: return true;
    116     case k21t: return true;
    117     case k22b: return true;
    118     case k22c: return true;
    119     case k22s: return true;
    120     case k22t: return true;
    121     case k22x: return true;
    122     case k23x: return true;
    123     case k31c: return true;
    124     case k31i: return true;
    125     case k31t: return true;
    126     case k32x: return true;
    127     case k51l: return true;
    128     default: return false;
    129   }
    130 }
    131 
    132 int32_t Instruction::VRegC() const {
    133   switch (FormatOf(Opcode())) {
    134     case k23x: return VRegC_23x();
    135     case k35c: return VRegC_35c();
    136     case k3rc: return VRegC_3rc();
    137     default: LOG(FATAL) << "Tried to access vC of instruction " << Name() <<
    138         " which has no C operand.";
    139   }
    140   return -1;
    141 }
    142 
    143 int32_t Instruction::VRegB() const {
    144   switch (FormatOf(Opcode())) {
    145     case k12x: return VRegB_12x();
    146     case k22b: return VRegB_22b();
    147     case k22c: return VRegB_22c();
    148     case k22s: return VRegB_22s();
    149     case k22t: return VRegB_22t();
    150     case k22x: return VRegB_22x();
    151     case k23x: return VRegB_23x();
    152     case k32x: return VRegB_32x();
    153     default: LOG(FATAL) << "Tried to access vB of instruction " << Name() <<
    154         " which has no B operand.";
    155   }
    156   return -1;
    157 }
    158 
    159 int32_t Instruction::VRegA() const {
    160   switch (FormatOf(Opcode())) {
    161     case k11n: return VRegA_11n();
    162     case k11x: return VRegA_11x();
    163     case k12x: return VRegA_12x();
    164     case k21c: return VRegA_21c();
    165     case k21h: return VRegA_21h();
    166     case k21s: return VRegA_21s();
    167     case k21t: return VRegA_21t();
    168     case k22b: return VRegA_22b();
    169     case k22c: return VRegA_22c();
    170     case k22s: return VRegA_22s();
    171     case k22t: return VRegA_22t();
    172     case k22x: return VRegA_22x();
    173     case k23x: return VRegA_23x();
    174     case k31c: return VRegA_31c();
    175     case k31i: return VRegA_31i();
    176     case k31t: return VRegA_31t();
    177     case k32x: return VRegA_32x();
    178     case k51l: return VRegA_51l();
    179     default: LOG(FATAL) << "Tried to access vA of instruction " << Name() <<
    180         " which has no A operand.";
    181   }
    182   return -1;
    183 }
    184 
    185 int32_t Instruction::GetTargetOffset() const {
    186   switch (FormatOf(Opcode())) {
    187     // Cases for conditional branches follow.
    188     case k22t: return VRegC_22t();
    189     case k21t: return VRegB_21t();
    190     // Cases for unconditional branches follow.
    191     case k10t: return VRegA_10t();
    192     case k20t: return VRegA_20t();
    193     case k30t: return VRegA_30t();
    194     default: LOG(FATAL) << "Tried to access the branch offset of an instruction " << Name() <<
    195         " which does not have a target operand.";
    196   }
    197   return 0;
    198 }
    199 
    200 bool Instruction::CanFlowThrough() const {
    201   const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
    202   uint16_t insn = *insns;
    203   Code opcode = static_cast<Code>(insn & 0xFF);
    204   return  FlagsOf(opcode) & Instruction::kContinue;
    205 }
    206 
    207 void Instruction::Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const {
    208   const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
    209   uint16_t insn = *insns;
    210   Code opcode = static_cast<Code>(insn & 0xFF);
    211 
    212   switch (FormatOf(opcode)) {
    213     case k10x:       // op
    214       /* nothing to do; copy the AA bits out for the verifier */
    215       vA = INST_AA(insn);
    216       break;
    217     case k12x:       // op vA, vB
    218       vA = INST_A(insn);
    219       vB = INST_B(insn);
    220       break;
    221     case k11n:       // op vA, #+B
    222       vA = INST_A(insn);
    223       vB = (int32_t) (INST_B(insn) << 28) >> 28;  // sign extend 4-bit value
    224       break;
    225     case k11x:       // op vAA
    226       vA = INST_AA(insn);
    227       break;
    228     case k10t:       // op +AA
    229       vA = (int8_t) INST_AA(insn);              // sign-extend 8-bit value
    230       break;
    231     case k20t:       // op +AAAA
    232       vA = (int16_t) FETCH(1);                   // sign-extend 16-bit value
    233       break;
    234     case k21c:       // op vAA, thing@BBBB
    235     case k22x:       // op vAA, vBBBB
    236       vA = INST_AA(insn);
    237       vB = FETCH(1);
    238       break;
    239     case k21s:       // op vAA, #+BBBB
    240     case k21t:       // op vAA, +BBBB
    241       vA = INST_AA(insn);
    242       vB = (int16_t) FETCH(1);                   // sign-extend 16-bit value
    243       break;
    244     case k21h:       // op vAA, #+BBBB0000[00000000]
    245       vA = INST_AA(insn);
    246       /*
    247        * The value should be treated as right-zero-extended, but we don't
    248        * actually do that here. Among other things, we don't know if it's
    249        * the top bits of a 32- or 64-bit value.
    250        */
    251       vB = FETCH(1);
    252       break;
    253     case k23x:       // op vAA, vBB, vCC
    254       vA = INST_AA(insn);
    255       vB = FETCH(1) & 0xff;
    256       vC = FETCH(1) >> 8;
    257       break;
    258     case k22b:       // op vAA, vBB, #+CC
    259       vA = INST_AA(insn);
    260       vB = FETCH(1) & 0xff;
    261       vC = (int8_t) (FETCH(1) >> 8);            // sign-extend 8-bit value
    262       break;
    263     case k22s:       // op vA, vB, #+CCCC
    264     case k22t:       // op vA, vB, +CCCC
    265       vA = INST_A(insn);
    266       vB = INST_B(insn);
    267       vC = (int16_t) FETCH(1);                   // sign-extend 16-bit value
    268       break;
    269     case k22c:       // op vA, vB, thing@CCCC
    270       vA = INST_A(insn);
    271       vB = INST_B(insn);
    272       vC = FETCH(1);
    273       break;
    274     case k30t:       // op +AAAAAAAA
    275       vA = FETCH_uint32(1);                     // signed 32-bit value
    276       break;
    277     case k31t:       // op vAA, +BBBBBBBB
    278     case k31c:       // op vAA, string@BBBBBBBB
    279       vA = INST_AA(insn);
    280       vB = FETCH_uint32(1);                     // 32-bit value
    281       break;
    282     case k32x:       // op vAAAA, vBBBB
    283       vA = FETCH(1);
    284       vB = FETCH(2);
    285       break;
    286     case k31i:       // op vAA, #+BBBBBBBB
    287       vA = INST_AA(insn);
    288       vB = FETCH_uint32(1);                     // signed 32-bit value
    289       break;
    290     case k35c:       // op {vC, vD, vE, vF, vG}, thing@BBBB
    291       {
    292         /*
    293          * Note that the fields mentioned in the spec don't appear in
    294          * their "usual" positions here compared to most formats. This
    295          * was done so that the field names for the argument count and
    296          * reference index match between this format and the corresponding
    297          * range formats (3rc and friends).
    298          *
    299          * Bottom line: The argument count is always in vA, and the
    300          * method constant (or equivalent) is always in vB.
    301          */
    302         uint16_t regList;
    303         int count;
    304 
    305         vA = INST_B(insn);  // This is labeled A in the spec.
    306         vB = FETCH(1);
    307         regList = FETCH(2);
    308 
    309         count = vA;
    310 
    311         /*
    312          * Copy the argument registers into the arg[] array, and
    313          * also copy the first argument (if any) into vC. (The
    314          * DecodedInstruction structure doesn't have separate
    315          * fields for {vD, vE, vF, vG}, so there's no need to make
    316          * copies of those.) Note that cases 5..2 fall through.
    317          */
    318         switch (count) {
    319         case 5: arg[4] = INST_A(insn);
    320         case 4: arg[3] = (regList >> 12) & 0x0f;
    321         case 3: arg[2] = (regList >> 8) & 0x0f;
    322         case 2: arg[1] = (regList >> 4) & 0x0f;
    323         case 1: vC = arg[0] = regList & 0x0f; break;
    324         case 0: break;  // Valid, but no need to do anything.
    325         default:
    326           LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
    327           return;
    328         }
    329       }
    330       break;
    331     case k3rc:       // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
    332       vA = INST_AA(insn);
    333       vB = FETCH(1);
    334       vC = FETCH(2);
    335         break;
    336     case k51l:       // op vAA, #+BBBBBBBBBBBBBBBB
    337       vA = INST_AA(insn);
    338       vB_wide = FETCH_uint32(1) | ((uint64_t) FETCH_uint32(3) << 32);
    339       break;
    340     default:
    341       LOG(ERROR) << "Can't decode unexpected format " << FormatOf(opcode) << " (op=" << opcode << ")";
    342       return;
    343   }
    344 }
    345 
    346 size_t Instruction::SizeInCodeUnitsComplexOpcode() const {
    347   const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
    348   // Handle special NOP encoded variable length sequences.
    349   switch (*insns) {
    350     case kPackedSwitchSignature:
    351       return (4 + insns[1] * 2);
    352     case kSparseSwitchSignature:
    353       return (2 + insns[1] * 4);
    354     case kArrayDataSignature: {
    355       uint16_t element_size = insns[1];
    356       uint32_t length = insns[2] | (((uint32_t)insns[3]) << 16);
    357       // The plus 1 is to round up for odd size and width.
    358       return (4 + (element_size * length + 1) / 2);
    359     }
    360     default:
    361       if ((*insns & 0xFF) == 0) {
    362         return 1;  // NOP.
    363       } else {
    364         LOG(FATAL) << "Unreachable: " << DumpString(NULL);
    365         return 0;
    366       }
    367   }
    368 }
    369 
    370 std::string Instruction::DumpHex(size_t code_units) const {
    371   size_t inst_length = SizeInCodeUnits();
    372   if (inst_length > code_units) {
    373     inst_length = code_units;
    374   }
    375   std::ostringstream os;
    376   const uint16_t* insn = reinterpret_cast<const uint16_t*>(this);
    377   for (size_t i = 0; i < inst_length; i++) {
    378     os << StringPrintf("0x%04x", insn[i]) << " ";
    379   }
    380   for (size_t i = inst_length; i < code_units; i++) {
    381     os << "       ";
    382   }
    383   return os.str();
    384 }
    385 
    386 std::string Instruction::DumpString(const DexFile* file) const {
    387   std::ostringstream os;
    388   const char* opcode = kInstructionNames[Opcode()];
    389   switch (FormatOf(Opcode())) {
    390     case k10x:  os << opcode; break;
    391     case k12x:  os << StringPrintf("%s v%d, v%d", opcode, VRegA_12x(), VRegB_12x()); break;
    392     case k11n:  os << StringPrintf("%s v%d, #%+d", opcode, VRegA_11n(), VRegB_11n()); break;
    393     case k11x:  os << StringPrintf("%s v%d", opcode, VRegA_11x()); break;
    394     case k10t:  os << StringPrintf("%s %+d", opcode, VRegA_10t()); break;
    395     case k20t:  os << StringPrintf("%s %+d", opcode, VRegA_20t()); break;
    396     case k22x:  os << StringPrintf("%s v%d, v%d", opcode, VRegA_22x(), VRegB_22x()); break;
    397     case k21t:  os << StringPrintf("%s v%d, %+d", opcode, VRegA_21t(), VRegB_21t()); break;
    398     case k21s:  os << StringPrintf("%s v%d, #%+d", opcode, VRegA_21s(), VRegB_21s()); break;
    399     case k21h: {
    400         // op vAA, #+BBBB0000[00000000]
    401         if (Opcode() == CONST_HIGH16) {
    402           uint32_t value = VRegB_21h() << 16;
    403           os << StringPrintf("%s v%d, #int %+d // 0x%x", opcode, VRegA_21h(), value, value);
    404         } else {
    405           uint64_t value = static_cast<uint64_t>(VRegB_21h()) << 48;
    406           os << StringPrintf("%s v%d, #long %+lld // 0x%llx", opcode, VRegA_21h(), value, value);
    407         }
    408       }
    409       break;
    410     case k21c: {
    411       switch (Opcode()) {
    412         case CONST_STRING:
    413           if (file != NULL) {
    414             uint32_t string_idx = VRegB_21c();
    415             os << StringPrintf("const-string v%d, %s // string@%d", VRegA_21c(),
    416                                PrintableString(file->StringDataByIdx(string_idx)).c_str(), string_idx);
    417             break;
    418           }  // else fall-through
    419         case CHECK_CAST:
    420         case CONST_CLASS:
    421         case NEW_INSTANCE:
    422           if (file != NULL) {
    423             uint32_t type_idx = VRegB_21c();
    424             os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyType(type_idx, *file)
    425                << " // type@" << type_idx;
    426             break;
    427           }  // else fall-through
    428         case SGET:
    429         case SGET_WIDE:
    430         case SGET_OBJECT:
    431         case SGET_BOOLEAN:
    432         case SGET_BYTE:
    433         case SGET_CHAR:
    434         case SGET_SHORT:
    435           if (file != NULL) {
    436             uint32_t field_idx = VRegB_21c();
    437             os << opcode << "  v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
    438                << " // field@" << field_idx;
    439             break;
    440           }  // else fall-through
    441         case SPUT:
    442         case SPUT_WIDE:
    443         case SPUT_OBJECT:
    444         case SPUT_BOOLEAN:
    445         case SPUT_BYTE:
    446         case SPUT_CHAR:
    447         case SPUT_SHORT:
    448           if (file != NULL) {
    449             uint32_t field_idx = VRegB_21c();
    450             os << opcode << " v" << static_cast<int>(VRegA_21c()) << ", " << PrettyField(field_idx, *file, true)
    451                << " // field@" << field_idx;
    452             break;
    453           }  // else fall-through
    454         default:
    455           os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_21c(), VRegB_21c());
    456           break;
    457       }
    458       break;
    459     }
    460     case k23x:  os << StringPrintf("%s v%d, v%d, v%d", opcode, VRegA_23x(), VRegB_23x(), VRegC_23x()); break;
    461     case k22b:  os << StringPrintf("%s v%d, v%d, #%+d", opcode, VRegA_22b(), VRegB_22b(), VRegC_22b()); break;
    462     case k22t:  os << StringPrintf("%s v%d, v%d, %+d", opcode, VRegA_22t(), VRegB_22t(), VRegC_22t()); break;
    463     case k22s:  os << StringPrintf("%s v%d, v%d, #%+d", opcode, VRegA_22s(), VRegB_22s(), VRegC_22s()); break;
    464     case k22c: {
    465       switch (Opcode()) {
    466         case IGET:
    467         case IGET_WIDE:
    468         case IGET_OBJECT:
    469         case IGET_BOOLEAN:
    470         case IGET_BYTE:
    471         case IGET_CHAR:
    472         case IGET_SHORT:
    473           if (file != NULL) {
    474             uint32_t field_idx = VRegC_22c();
    475             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    476                << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
    477             break;
    478           }  // else fall-through
    479         case IGET_QUICK:
    480         case IGET_OBJECT_QUICK:
    481           if (file != NULL) {
    482             uint32_t field_idx = VRegC_22c();
    483             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    484                << "// offset@" << field_idx;
    485             break;
    486           }  // else fall-through
    487         case IPUT:
    488         case IPUT_WIDE:
    489         case IPUT_OBJECT:
    490         case IPUT_BOOLEAN:
    491         case IPUT_BYTE:
    492         case IPUT_CHAR:
    493         case IPUT_SHORT:
    494           if (file != NULL) {
    495             uint32_t field_idx = VRegC_22c();
    496             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    497                << PrettyField(field_idx, *file, true) << " // field@" << field_idx;
    498             break;
    499           }  // else fall-through
    500         case IPUT_QUICK:
    501         case IPUT_OBJECT_QUICK:
    502           if (file != NULL) {
    503             uint32_t field_idx = VRegC_22c();
    504             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    505                << "// offset@" << field_idx;
    506             break;
    507           }  // else fall-through
    508         case INSTANCE_OF:
    509           if (file != NULL) {
    510             uint32_t type_idx = VRegC_22c();
    511             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    512                << PrettyType(type_idx, *file) << " // type@" << type_idx;
    513             break;
    514           }
    515         case NEW_ARRAY:
    516           if (file != NULL) {
    517             uint32_t type_idx = VRegC_22c();
    518             os << opcode << " v" << static_cast<int>(VRegA_22c()) << ", v" << static_cast<int>(VRegB_22c()) << ", "
    519                << PrettyType(type_idx, *file) << " // type@" << type_idx;
    520             break;
    521           }  // else fall-through
    522         default:
    523           os << StringPrintf("%s v%d, v%d, thing@%d", opcode, VRegA_22c(), VRegB_22c(), VRegC_22c());
    524           break;
    525       }
    526       break;
    527     }
    528     case k32x:  os << StringPrintf("%s v%d, v%d", opcode, VRegA_32x(), VRegB_32x()); break;
    529     case k30t:  os << StringPrintf("%s %+d", opcode, VRegA_30t()); break;
    530     case k31t:  os << StringPrintf("%s v%d, %+d", opcode, VRegA_31t(), VRegB_31t()); break;
    531     case k31i:  os << StringPrintf("%s v%d, #%+d", opcode, VRegA_31i(), VRegB_31i()); break;
    532     case k31c:
    533       if (Opcode() == CONST_STRING_JUMBO) {
    534         uint32_t string_idx = VRegB_31c();
    535         if (file != NULL) {
    536           os << StringPrintf("%s v%d, %s // string@%d", opcode, VRegA_31c(),
    537                              PrintableString(file->StringDataByIdx(string_idx)).c_str(),
    538                              string_idx);
    539         } else {
    540           os << StringPrintf("%s v%d, string@%d", opcode, VRegA_31c(), string_idx);
    541         }
    542       } else {
    543         os << StringPrintf("%s v%d, thing@%d", opcode, VRegA_31c(), VRegB_31c()); break;
    544       }
    545       break;
    546     case k35c: {
    547       uint32_t arg[5];
    548       GetArgs(arg);
    549       switch (Opcode()) {
    550         case INVOKE_VIRTUAL:
    551         case INVOKE_SUPER:
    552         case INVOKE_DIRECT:
    553         case INVOKE_STATIC:
    554         case INVOKE_INTERFACE:
    555           if (file != NULL) {
    556             os << opcode << " {";
    557             uint32_t method_idx = VRegB_35c();
    558             for (size_t i = 0; i < VRegA_35c(); ++i) {
    559               if (i != 0) {
    560                 os << ", ";
    561               }
    562               os << "v" << arg[i];
    563             }
    564             os << "}, " << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
    565             break;
    566           }  // else fall-through
    567         case INVOKE_VIRTUAL_QUICK:
    568           if (file != NULL) {
    569             os << opcode << " {";
    570             uint32_t method_idx = VRegB_35c();
    571             for (size_t i = 0; i < VRegA_35c(); ++i) {
    572               if (i != 0) {
    573                 os << ", ";
    574               }
    575               os << "v" << arg[i];
    576             }
    577             os << "},  // vtable@" << method_idx;
    578             break;
    579           }  // else fall-through
    580         default:
    581           os << opcode << " {v" << arg[0] << ", v" << arg[1] << ", v" << arg[2]
    582                        << ", v" << arg[3] << ", v" << arg[4] << "}, thing@" << VRegB_35c();
    583           break;
    584       }
    585       break;
    586     }
    587     case k3rc: {
    588       switch (Opcode()) {
    589         case INVOKE_VIRTUAL_RANGE:
    590         case INVOKE_SUPER_RANGE:
    591         case INVOKE_DIRECT_RANGE:
    592         case INVOKE_STATIC_RANGE:
    593         case INVOKE_INTERFACE_RANGE:
    594           if (file != NULL) {
    595             uint32_t method_idx = VRegB_3rc();
    596             os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
    597                << PrettyMethod(method_idx, *file) << " // method@" << method_idx;
    598             break;
    599           }  // else fall-through
    600         case INVOKE_VIRTUAL_RANGE_QUICK:
    601           if (file != NULL) {
    602             uint32_t method_idx = VRegB_3rc();
    603             os << StringPrintf("%s, {v%d .. v%d}, ", opcode, VRegC_3rc(), (VRegC_3rc() + VRegA_3rc() - 1))
    604                << "// vtable@" << method_idx;
    605             break;
    606           }  // else fall-through
    607         default:
    608           os << StringPrintf("%s, {v%d .. v%d}, thing@%d", opcode, VRegC_3rc(),
    609                              (VRegC_3rc() + VRegA_3rc() - 1), VRegB_3rc());
    610           break;
    611       }
    612       break;
    613     }
    614     case k51l: os << StringPrintf("%s v%d, #%+lld", opcode, VRegA_51l(), VRegB_51l()); break;
    615     default: os << " unknown format (" << DumpHex(5) << ")"; break;
    616   }
    617   return os.str();
    618 }
    619 
    620 std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) {
    621   return os << Instruction::Name(code);
    622 }
    623 
    624 }  // namespace art
    625